blob: c14e76fd0267caa061da4b9c2d02d32bd4f61eb8 [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 <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <memory>
#include <set>
#include <sstream>
#include <tuple>
#include <vector>
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/system/sys_info.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "storage/browser/quota/quota_database.h"
#include "storage/browser/quota/quota_features.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/test/mock_special_storage_policy.h"
#include "storage/browser/test/mock_storage_client.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
using blink::mojom::QuotaStatusCode;
using blink::mojom::StorageType;
using storage::QuotaClient;
using storage::QuotaManager;
using storage::UsageInfo;
using storage::UsageInfoEntries;
namespace content {
namespace {
// For shorter names.
const StorageType kTemp = StorageType::kTemporary;
const StorageType kPerm = StorageType::kPersistent;
const StorageType kSync = StorageType::kSyncable;
const int kAllClients = QuotaClient::kAllClientsMask;
// Values in bytes.
const int64_t kAvailableSpaceForApp = 13377331U;
const int64_t kMustRemainAvailableForSystem = kAvailableSpaceForApp / 2;
const int64_t kDefaultPoolSize = 1000;
const int64_t kDefaultPerHostQuota = 200;
const GURL kTestEvictionOrigin = GURL("http://test.eviction.policy/result");
// Returns a deterministic value for the amount of available disk space.
int64_t GetAvailableDiskSpaceForTest() {
return kAvailableSpaceForApp + kMustRemainAvailableForSystem;
}
std::tuple<int64_t, int64_t> GetVolumeInfoForTests(
const base::FilePath& unused) {
int64_t available = static_cast<uint64_t>(GetAvailableDiskSpaceForTest());
int64_t total = available * 2;
return std::make_tuple(total, available);
}
// TODO(crbug.com/889590): Replace with common converter.
url::Origin ToOrigin(const std::string& url) {
return url::Origin::Create(GURL(url));
}
} // namespace
class QuotaManagerTest : public testing::Test {
protected:
using QuotaTableEntry = QuotaManager::QuotaTableEntry;
using QuotaTableEntries = QuotaManager::QuotaTableEntries;
using OriginInfoTableEntries = QuotaManager::OriginInfoTableEntries;
public:
QuotaManagerTest()
: mock_time_counter_(0),
weak_factory_(this) {
}
void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
mock_special_storage_policy_ = new MockSpecialStoragePolicy;
ResetQuotaManager(false /* is_incognito */);
}
void TearDown() override {
// Make sure the quota manager cleans up correctly.
quota_manager_ = nullptr;
scoped_task_environment_.RunUntilIdle();
}
protected:
void ResetQuotaManager(bool is_incognito) {
quota_manager_ = new QuotaManager(is_incognito, data_dir_.GetPath(),
base::ThreadTaskRunnerHandle::Get().get(),
mock_special_storage_policy_.get(),
storage::GetQuotaSettingsFunc());
SetQuotaSettings(kDefaultPoolSize, kDefaultPerHostQuota,
is_incognito ? INT64_C(0) : kMustRemainAvailableForSystem);
// Don't (automatically) start the eviction for testing.
quota_manager_->eviction_disabled_ = true;
// Don't query the hard disk for remaining capacity.
quota_manager_->get_volume_info_fn_= &GetVolumeInfoForTests;
additional_callback_count_ = 0;
}
MockStorageClient* CreateClient(
const MockOriginData* mock_data,
size_t mock_data_size,
QuotaClient::ID id) {
return new MockStorageClient(quota_manager_->proxy(),
mock_data, id, mock_data_size);
}
void RegisterClient(MockStorageClient* client) {
quota_manager_->proxy()->RegisterClient(client);
}
void GetUsageInfo() {
usage_info_.clear();
quota_manager_->GetUsageInfo(base::BindOnce(
&QuotaManagerTest::DidGetUsageInfo, weak_factory_.GetWeakPtr()));
}
void GetUsageAndQuotaForWebApps(const url::Origin& origin, StorageType type) {
quota_status_ = QuotaStatusCode::kUnknown;
usage_ = -1;
quota_ = -1;
quota_manager_->GetUsageAndQuotaForWebApps(
origin, type,
base::BindOnce(&QuotaManagerTest::DidGetUsageAndQuota,
weak_factory_.GetWeakPtr()));
}
void GetUsageAndQuotaWithBreakdown(const url::Origin& origin,
StorageType type) {
quota_status_ = QuotaStatusCode::kUnknown;
usage_ = -1;
quota_ = -1;
usage_breakdown_ = nullptr;
quota_manager_->GetUsageAndQuotaWithBreakdown(
origin, type,
base::BindOnce(&QuotaManagerTest::DidGetUsageAndQuotaWithBreakdown,
weak_factory_.GetWeakPtr()));
}
void GetUsageAndQuotaForStorageClient(const url::Origin& origin,
StorageType type) {
quota_status_ = QuotaStatusCode::kUnknown;
usage_ = -1;
quota_ = -1;
quota_manager_->GetUsageAndQuota(
origin, type,
base::BindOnce(&QuotaManagerTest::DidGetUsageAndQuota,
weak_factory_.GetWeakPtr()));
}
void SetQuotaSettings(int64_t pool_size,
int64_t per_host_quota,
int64_t must_remain_available) {
storage::QuotaSettings settings;
settings.pool_size = pool_size;
settings.per_host_quota = per_host_quota;
settings.session_only_per_host_quota =
(per_host_quota > 0) ? (per_host_quota - 1) : 0;
settings.must_remain_available = must_remain_available;
settings.refresh_interval = base::TimeDelta::Max();
quota_manager_->SetQuotaSettings(settings);
}
void GetPersistentHostQuota(const std::string& host) {
quota_status_ = QuotaStatusCode::kUnknown;
quota_ = -1;
quota_manager_->GetPersistentHostQuota(
host, base::BindOnce(&QuotaManagerTest::DidGetHostQuota,
weak_factory_.GetWeakPtr()));
}
void SetPersistentHostQuota(const std::string& host, int64_t new_quota) {
quota_status_ = QuotaStatusCode::kUnknown;
quota_ = -1;
quota_manager_->SetPersistentHostQuota(
host, new_quota,
base::BindOnce(&QuotaManagerTest::DidGetHostQuota,
weak_factory_.GetWeakPtr()));
}
void GetGlobalUsage(StorageType type) {
usage_ = -1;
unlimited_usage_ = -1;
quota_manager_->GetGlobalUsage(
type, base::BindOnce(&QuotaManagerTest::DidGetGlobalUsage,
weak_factory_.GetWeakPtr()));
}
void GetHostUsage(const std::string& host, StorageType type) {
usage_ = -1;
quota_manager_->GetHostUsage(
host, type,
base::BindOnce(&QuotaManagerTest::DidGetHostUsage,
weak_factory_.GetWeakPtr()));
}
void GetHostUsageBreakdown(const std::string& host, StorageType type) {
usage_ = -1;
quota_manager_->GetHostUsageWithBreakdown(
host, type,
base::BindOnce(&QuotaManagerTest::DidGetHostUsageBreakdown,
weak_factory_.GetWeakPtr()));
}
void RunAdditionalUsageAndQuotaTask(const url::Origin& origin,
StorageType type) {
quota_manager_->GetUsageAndQuota(
origin, type,
base::BindOnce(&QuotaManagerTest::DidGetUsageAndQuotaAdditional,
weak_factory_.GetWeakPtr()));
}
void DeleteClientOriginData(QuotaClient* client,
const url::Origin& origin,
StorageType type) {
DCHECK(client);
quota_status_ = QuotaStatusCode::kUnknown;
client->DeleteOriginData(origin, type,
base::BindOnce(&QuotaManagerTest::StatusCallback,
weak_factory_.GetWeakPtr()));
}
void EvictOriginData(const url::Origin& origin, StorageType type) {
quota_status_ = QuotaStatusCode::kUnknown;
quota_manager_->EvictOriginData(
origin, type,
base::BindOnce(&QuotaManagerTest::StatusCallback,
weak_factory_.GetWeakPtr()));
}
void DeleteOriginData(const url::Origin& origin,
StorageType type,
int quota_client_mask) {
quota_status_ = QuotaStatusCode::kUnknown;
quota_manager_->DeleteOriginData(
origin, type, quota_client_mask,
base::BindOnce(&QuotaManagerTest::StatusCallback,
weak_factory_.GetWeakPtr()));
}
void DeleteHostData(const std::string& host,
StorageType type,
int quota_client_mask) {
quota_status_ = QuotaStatusCode::kUnknown;
quota_manager_->DeleteHostData(
host, type, quota_client_mask,
base::BindOnce(&QuotaManagerTest::StatusCallback,
weak_factory_.GetWeakPtr()));
}
void GetStorageCapacity() {
available_space_ = -1;
total_space_ = -1;
quota_manager_->GetStorageCapacity(base::BindOnce(
&QuotaManagerTest::DidGetStorageCapacity, weak_factory_.GetWeakPtr()));
}
void GetEvictionRoundInfo() {
quota_status_ = QuotaStatusCode::kUnknown;
settings_ = storage::QuotaSettings();
available_space_ = -1;
total_space_ = -1;
usage_ = -1;
quota_manager_->GetEvictionRoundInfo(
base::BindOnce(&QuotaManagerTest::DidGetEvictionRoundInfo,
weak_factory_.GetWeakPtr()));
}
void GetCachedOrigins(StorageType type, std::set<url::Origin>* origins) {
ASSERT_TRUE(origins != nullptr);
origins->clear();
quota_manager_->GetCachedOrigins(type, origins);
}
void NotifyStorageAccessed(QuotaClient* client,
const url::Origin& origin,
StorageType type) {
DCHECK(client);
quota_manager_->NotifyStorageAccessedInternal(
client->id(), origin, type, IncrementMockTime());
}
void DeleteOriginFromDatabase(const url::Origin& origin, StorageType type) {
quota_manager_->DeleteOriginFromDatabase(origin, type, false);
}
void GetEvictionOrigin(StorageType type) {
eviction_origin_.reset();
// The quota manager's default eviction policy is to use an LRU eviction
// policy.
quota_manager_->GetEvictionOrigin(
type, std::set<url::Origin>(), 0,
base::BindOnce(&QuotaManagerTest::DidGetEvictionOrigin,
weak_factory_.GetWeakPtr()));
}
void NotifyOriginInUse(const url::Origin& origin) {
quota_manager_->NotifyOriginInUse(origin);
}
void NotifyOriginNoLongerInUse(const url::Origin& origin) {
quota_manager_->NotifyOriginNoLongerInUse(origin);
}
void GetOriginsModifiedSince(StorageType type, base::Time modified_since) {
modified_origins_.clear();
modified_origins_type_ = StorageType::kUnknown;
quota_manager_->GetOriginsModifiedSince(
type, modified_since,
base::BindOnce(&QuotaManagerTest::DidGetModifiedOrigins,
weak_factory_.GetWeakPtr()));
}
void DumpQuotaTable() {
quota_entries_.clear();
quota_manager_->DumpQuotaTable(base::BindOnce(
&QuotaManagerTest::DidDumpQuotaTable, weak_factory_.GetWeakPtr()));
}
void DumpOriginInfoTable() {
origin_info_entries_.clear();
quota_manager_->DumpOriginInfoTable(base::BindOnce(
&QuotaManagerTest::DidDumpOriginInfoTable, weak_factory_.GetWeakPtr()));
}
void DidGetUsageInfo(UsageInfoEntries entries) {
usage_info_ = std::move(entries);
}
void DidGetUsageAndQuota(QuotaStatusCode status,
int64_t usage,
int64_t quota) {
quota_status_ = status;
usage_ = usage;
quota_ = quota;
}
void DidGetUsageAndQuotaWithBreakdown(
QuotaStatusCode status,
int64_t usage,
int64_t quota,
blink::mojom::UsageBreakdownPtr usage_breakdown) {
quota_status_ = status;
usage_ = usage;
quota_ = quota;
usage_breakdown_ = std::move(usage_breakdown);
}
void DidGetQuota(QuotaStatusCode status, int64_t quota) {
quota_status_ = status;
quota_ = quota;
}
void DidGetStorageCapacity(int64_t total_space, int64_t available_space) {
total_space_ = total_space;
available_space_ = available_space;
}
void DidGetHostQuota(QuotaStatusCode status, int64_t quota) {
quota_status_ = status;
quota_ = quota;
}
void DidGetGlobalUsage(int64_t usage, int64_t unlimited_usage) {
usage_ = usage;
unlimited_usage_ = unlimited_usage;
}
void DidGetHostUsage(int64_t usage) { usage_ = usage; }
void StatusCallback(QuotaStatusCode status) {
++status_callback_count_;
quota_status_ = status;
}
void DidGetHostUsageBreakdown(
int64_t usage,
blink::mojom::UsageBreakdownPtr usage_breakdown) {
usage_ = usage;
usage_breakdown_ = std::move(usage_breakdown);
}
void DidGetEvictionRoundInfo(QuotaStatusCode status,
const storage::QuotaSettings& settings,
int64_t available_space,
int64_t total_space,
int64_t global_usage,
bool global_usage_is_complete) {
quota_status_ = status;
settings_ = settings;
available_space_ = available_space;
total_space_ = total_space;
usage_ = global_usage;
}
void DidGetEvictionOrigin(const base::Optional<url::Origin>& origin) {
eviction_origin_ = origin;
DCHECK(!origin.has_value() || !origin->GetURL().is_empty());
}
void DidGetModifiedOrigins(const std::set<url::Origin>& origins,
StorageType type) {
modified_origins_ = origins;
modified_origins_type_ = type;
}
void DidDumpQuotaTable(const QuotaTableEntries& entries) {
quota_entries_ = entries;
}
void DidDumpOriginInfoTable(const OriginInfoTableEntries& entries) {
origin_info_entries_ = entries;
}
void GetUsage_WithModifyTestBody(const StorageType type);
void set_additional_callback_count(int c) { additional_callback_count_ = c; }
int additional_callback_count() const { return additional_callback_count_; }
void DidGetUsageAndQuotaAdditional(QuotaStatusCode status,
int64_t usage,
int64_t quota) {
++additional_callback_count_;
}
QuotaManager* quota_manager() const { return quota_manager_.get(); }
void set_quota_manager(QuotaManager* quota_manager) {
quota_manager_ = quota_manager;
}
MockSpecialStoragePolicy* mock_special_storage_policy() const {
return mock_special_storage_policy_.get();
}
QuotaStatusCode status() const { return quota_status_; }
const UsageInfoEntries& usage_info() const { return usage_info_; }
int64_t usage() const { return usage_; }
const blink::mojom::UsageBreakdown& usage_breakdown() const {
return *usage_breakdown_;
}
int64_t limited_usage() const { return limited_usage_; }
int64_t unlimited_usage() const { return unlimited_usage_; }
int64_t quota() const { return quota_; }
int64_t total_space() const { return total_space_; }
int64_t available_space() const { return available_space_; }
const base::Optional<url::Origin>& eviction_origin() const {
return eviction_origin_;
}
const std::set<url::Origin>& modified_origins() const {
return modified_origins_;
}
StorageType modified_origins_type() const { return modified_origins_type_; }
const QuotaTableEntries& quota_entries() const { return quota_entries_; }
const OriginInfoTableEntries& origin_info_entries() const {
return origin_info_entries_;
}
const storage::QuotaSettings& settings() const { return settings_; }
base::FilePath profile_path() const { return data_dir_.GetPath(); }
int status_callback_count() const { return status_callback_count_; }
void reset_status_callback_count() { status_callback_count_ = 0; }
protected:
base::test::ScopedFeatureList scoped_feature_list_;
base::test::ScopedTaskEnvironment scoped_task_environment_;
private:
base::Time IncrementMockTime() {
++mock_time_counter_;
return base::Time::FromDoubleT(mock_time_counter_ * 10.0);
}
base::ScopedTempDir data_dir_;
scoped_refptr<QuotaManager> quota_manager_;
scoped_refptr<MockSpecialStoragePolicy> mock_special_storage_policy_;
QuotaStatusCode quota_status_;
UsageInfoEntries usage_info_;
int64_t usage_;
blink::mojom::UsageBreakdownPtr usage_breakdown_;
int64_t limited_usage_;
int64_t unlimited_usage_;
int64_t quota_;
int64_t total_space_;
int64_t available_space_;
base::Optional<url::Origin> eviction_origin_;
std::set<url::Origin> modified_origins_;
StorageType modified_origins_type_;
QuotaTableEntries quota_entries_;
OriginInfoTableEntries origin_info_entries_;
storage::QuotaSettings settings_;
int status_callback_count_;
int additional_callback_count_;
int mock_time_counter_;
base::WeakPtrFactory<QuotaManagerTest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(QuotaManagerTest);
};
TEST_F(QuotaManagerTest, GetUsageInfo) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com:8080/", kTemp, 15 },
{ "http://bar.com/", kTemp, 20 },
{ "http://bar.com/", kPerm, 50 },
};
static const MockOriginData kData2[] = {
{ "https://foo.com/", kTemp, 30 },
{ "https://foo.com:8081/", kTemp, 35 },
{ "http://bar.com/", kPerm, 40 },
{ "http://example.com/", kPerm, 40 },
};
RegisterClient(
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem));
RegisterClient(
CreateClient(kData2, base::size(kData2), QuotaClient::kDatabase));
GetUsageInfo();
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(4U, usage_info().size());
for (size_t i = 0; i < usage_info().size(); ++i) {
const UsageInfo& info = usage_info()[i];
if (info.host == "foo.com" && info.type == kTemp) {
EXPECT_EQ(10 + 15 + 30 + 35, info.usage);
} else if (info.host == "bar.com" && info.type == kTemp) {
EXPECT_EQ(20, info.usage);
} else if (info.host == "bar.com" && info.type == kPerm) {
EXPECT_EQ(50 + 40, info.usage);
} else if (info.host == "example.com" && info.type == kPerm) {
EXPECT_EQ(40, info.usage);
} else {
ADD_FAILURE() << "Unexpected host, type: " << info.host << ", "
<< static_cast<int>(info.type);
}
}
}
TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com/", kPerm, 80 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(80, usage());
EXPECT_EQ(0, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10, usage());
EXPECT_LE(0, quota());
int64_t quota_returned_for_foo = quota();
GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
EXPECT_EQ(quota_returned_for_foo, quota());
}
TEST_F(QuotaManagerTest, GetUsage_NoClient) {
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
EXPECT_EQ(0, unlimited_usage());
GetGlobalUsage(kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
EXPECT_EQ(0, unlimited_usage());
}
TEST_F(QuotaManagerTest, GetUsage_EmptyClient) {
RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem));
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
EXPECT_EQ(0, unlimited_usage());
GetGlobalUsage(kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
EXPECT_EQ(0, unlimited_usage());
}
TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com:8080/", kTemp, 20 },
{ "http://bar.com/", kTemp, 5 },
{ "https://bar.com/", kTemp, 7 },
{ "http://baz.com/", kTemp, 30 },
{ "http://foo.com/", kPerm, 40 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
// This time explicitly sets a temporary global quota.
const int kPoolSize = 100;
const int kPerHostQuota = 20;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20, usage());
// The host's quota should be its full portion of the global quota
// since there's plenty of diskspace.
EXPECT_EQ(kPerHostQuota, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(5 + 7, usage());
EXPECT_EQ(kPerHostQuota, quota());
}
TEST_F(QuotaManagerTest, GetUsage_MultipleClients) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://bar.com/", kTemp, 2 },
{ "http://bar.com/", kPerm, 4 },
{ "http://unlimited/", kPerm, 8 },
};
static const MockOriginData kData2[] = {
{ "https://foo.com/", kTemp, 128 },
{ "http://example.com/", kPerm, 256 },
{ "http://unlimited/", kTemp, 512 },
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
RegisterClient(
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem));
RegisterClient(
CreateClient(kData2, base::size(kData2), QuotaClient::kDatabase));
const int64_t kPoolSize = GetAvailableDiskSpaceForTest();
const int64_t kPerHostQuota = kPoolSize / 5;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(1 + 128, usage());
EXPECT_EQ(kPerHostQuota, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(4, usage());
EXPECT_EQ(0, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(512, usage());
EXPECT_EQ(kAvailableSpaceForApp + usage(), quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(8, usage());
EXPECT_EQ(kAvailableSpaceForApp + usage(), quota());
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(1 + 2 + 128 + 512, usage());
EXPECT_EQ(512, unlimited_usage());
GetGlobalUsage(kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(4 + 8 + 256, usage());
EXPECT_EQ(8, unlimited_usage());
}
TEST_F(QuotaManagerTest, GetUsageWithBreakdown_Simple) {
blink::mojom::UsageBreakdown usage_breakdown_expected =
blink::mojom::UsageBreakdown();
static const MockOriginData kData1[] = {
{"http://foo.com/", kTemp, 1}, {"http://foo.com/", kPerm, 80},
};
static const MockOriginData kData2[] = {
{"http://foo.com/", kTemp, 4},
};
static const MockOriginData kData3[] = {
{"http://foo.com/", kTemp, 8},
};
MockStorageClient* client1 =
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem);
MockStorageClient* client2 =
CreateClient(kData2, base::size(kData2), QuotaClient::kDatabase);
MockStorageClient* client3 =
CreateClient(kData3, base::size(kData3), QuotaClient::kAppcache);
RegisterClient(client1);
RegisterClient(client2);
RegisterClient(client3);
GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(80, usage());
usage_breakdown_expected.fileSystem = 80;
usage_breakdown_expected.webSql = 0;
usage_breakdown_expected.appcache = 0;
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(1 + 4 + 8, usage());
usage_breakdown_expected.fileSystem = 1;
usage_breakdown_expected.webSql = 4;
usage_breakdown_expected.appcache = 8;
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
GetUsageAndQuotaWithBreakdown(ToOrigin("http://bar.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
usage_breakdown_expected.fileSystem = 0;
usage_breakdown_expected.webSql = 0;
usage_breakdown_expected.appcache = 0;
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
}
TEST_F(QuotaManagerTest, GetUsageWithBreakdown_NoClient) {
blink::mojom::UsageBreakdown usage_breakdown_expected =
blink::mojom::UsageBreakdown();
GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
GetHostUsageBreakdown("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
GetHostUsageBreakdown("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
}
TEST_F(QuotaManagerTest, GetUsageWithBreakdown_MultiOrigins) {
blink::mojom::UsageBreakdown usage_breakdown_expected =
blink::mojom::UsageBreakdown();
static const MockOriginData kData[] = {
{"http://foo.com/", kTemp, 10}, {"http://foo.com:8080/", kTemp, 20},
{"http://bar.com/", kTemp, 5}, {"https://bar.com/", kTemp, 7},
{"http://baz.com/", kTemp, 30}, {"http://foo.com/", kPerm, 40},
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20, usage());
usage_breakdown_expected.fileSystem = 10 + 20;
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
GetUsageAndQuotaWithBreakdown(ToOrigin("http://bar.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(5 + 7, usage());
usage_breakdown_expected.fileSystem = 5 + 7;
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
}
TEST_F(QuotaManagerTest, GetUsageWithBreakdown_MultipleClients) {
blink::mojom::UsageBreakdown usage_breakdown_expected =
blink::mojom::UsageBreakdown();
static const MockOriginData kData1[] = {
{"http://foo.com/", kTemp, 1},
{"http://bar.com/", kTemp, 2},
{"http://bar.com/", kPerm, 4},
{"http://unlimited/", kPerm, 8},
};
static const MockOriginData kData2[] = {
{"https://foo.com/", kTemp, 128},
{"http://example.com/", kPerm, 256},
{"http://unlimited/", kTemp, 512},
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
RegisterClient(
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem));
RegisterClient(
CreateClient(kData2, base::size(kData2), QuotaClient::kDatabase));
GetUsageAndQuotaWithBreakdown(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(1 + 128, usage());
usage_breakdown_expected.fileSystem = 1;
usage_breakdown_expected.webSql = 128;
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
GetUsageAndQuotaWithBreakdown(ToOrigin("http://bar.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(4, usage());
usage_breakdown_expected.fileSystem = 4;
usage_breakdown_expected.webSql = 0;
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
GetUsageAndQuotaWithBreakdown(ToOrigin("http://unlimited/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(512, usage());
usage_breakdown_expected.fileSystem = 0;
usage_breakdown_expected.webSql = 512;
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
GetUsageAndQuotaWithBreakdown(ToOrigin("http://unlimited/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(8, usage());
usage_breakdown_expected.fileSystem = 8;
usage_breakdown_expected.webSql = 0;
EXPECT_TRUE(usage_breakdown_expected.Equals(usage_breakdown()));
}
void QuotaManagerTest::GetUsage_WithModifyTestBody(const StorageType type) {
const MockOriginData data[] = {
{ "http://foo.com/", type, 10 },
{ "http://foo.com:1/", type, 20 },
};
MockStorageClient* client =
CreateClient(data, base::size(data), QuotaClient::kFileSystem);
RegisterClient(client);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), type);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20, usage());
client->ModifyOriginAndNotify(ToOrigin("http://foo.com/"), type, 30);
client->ModifyOriginAndNotify(ToOrigin("http://foo.com:1/"), type, -5);
client->AddOriginAndNotify(ToOrigin("https://foo.com/"), type, 1);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), type);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20 + 30 - 5 + 1, usage());
int foo_usage = usage();
client->AddOriginAndNotify(ToOrigin("http://bar.com/"), type, 40);
GetUsageAndQuotaForWebApps(ToOrigin("http://bar.com/"), type);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(40, usage());
GetGlobalUsage(type);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(foo_usage + 40, usage());
EXPECT_EQ(0, unlimited_usage());
}
TEST_F(QuotaManagerTest, GetTemporaryUsage_WithModify) {
GetUsage_WithModifyTestBody(kTemp);
}
TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com:8080/", kTemp, 20 },
{ "http://bar.com/", kTemp, 13 },
{ "http://foo.com/", kPerm, 40 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
const int kPoolSize = 100;
const int kPerHostQuota = 20;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20, usage());
EXPECT_EQ(kPerHostQuota, quota());
set_additional_callback_count(0);
RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kTemp);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20, usage());
EXPECT_EQ(kPerHostQuota, quota());
EXPECT_EQ(2, additional_callback_count());
}
TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_NukeManager) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com:8080/", kTemp, 20 },
{ "http://bar.com/", kTemp, 13 },
{ "http://foo.com/", kPerm, 40 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
const int kPoolSize = 100;
const int kPerHostQuota = 20;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
set_additional_callback_count(0);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kTemp);
RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kTemp);
DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, kAllClients);
DeleteOriginData(ToOrigin("http://bar.com/"), kTemp, kAllClients);
// Nuke before waiting for callbacks.
set_quota_manager(nullptr);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kErrorAbort, status());
}
TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Overbudget) {
static const MockOriginData kData[] = {
{ "http://usage1/", kTemp, 1 },
{ "http://usage10/", kTemp, 10 },
{ "http://usage200/", kTemp, 200 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
const int kPoolSize = 100;
const int kPerHostQuota = 20;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
// Provided diskspace is not tight, global usage does not affect the
// quota calculations for an individual origin, so despite global usage
// in excess of our poolsize, we still get the nominal quota value.
GetStorageCapacity();
scoped_task_environment_.RunUntilIdle();
EXPECT_LE(kMustRemainAvailableForSystem, available_space());
GetUsageAndQuotaForWebApps(ToOrigin("http://usage1/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(1, usage());
EXPECT_EQ(kPerHostQuota, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10, usage());
EXPECT_EQ(kPerHostQuota, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://usage200/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(200, usage());
EXPECT_EQ(kPerHostQuota, quota()); // should be clamped to the nominal quota
}
TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) {
static const MockOriginData kData[] = {
{ "http://usage10/", kTemp, 10 },
{ "http://usage50/", kTemp, 50 },
{ "http://unlimited/", kTemp, 4000 },
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
// Test when not overbugdet.
const int kPerHostQuotaFor1000 = 200;
SetQuotaSettings(1000, kPerHostQuotaFor1000, kMustRemainAvailableForSystem);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(10 + 50 + 4000, usage());
EXPECT_EQ(4000, unlimited_usage());
GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10, usage());
EXPECT_EQ(kPerHostQuotaFor1000, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://usage50/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(50, usage());
EXPECT_EQ(kPerHostQuotaFor1000, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(4000, usage());
EXPECT_EQ(kAvailableSpaceForApp + usage(), quota());
GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
EXPECT_EQ(QuotaManager::kNoLimit, quota());
// Test when overbugdet.
const int kPerHostQuotaFor100 = 20;
SetQuotaSettings(100, kPerHostQuotaFor100, kMustRemainAvailableForSystem);
GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10, usage());
EXPECT_EQ(kPerHostQuotaFor100, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://usage50/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(50, usage());
EXPECT_EQ(kPerHostQuotaFor100, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(4000, usage());
EXPECT_EQ(kAvailableSpaceForApp + usage(), quota());
GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
EXPECT_EQ(QuotaManager::kNoLimit, quota());
// Revoke the unlimited rights and make sure the change is noticed.
mock_special_storage_policy()->Reset();
mock_special_storage_policy()->NotifyCleared();
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(10 + 50 + 4000, usage());
EXPECT_EQ(0, unlimited_usage());
GetUsageAndQuotaForWebApps(ToOrigin("http://usage10/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10, usage());
EXPECT_EQ(kPerHostQuotaFor100, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://usage50/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(50, usage());
EXPECT_EQ(kPerHostQuotaFor100, quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(4000, usage());
EXPECT_EQ(kPerHostQuotaFor100, quota());
GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(4000, usage());
EXPECT_EQ(kPerHostQuotaFor100, quota());
}
TEST_F(QuotaManagerTest, OriginInUse) {
const url::Origin kFooOrigin = ToOrigin("http://foo.com/");
const url::Origin kBarOrigin = ToOrigin("http://bar.com/");
EXPECT_FALSE(quota_manager()->IsOriginInUse(kFooOrigin));
quota_manager()->NotifyOriginInUse(kFooOrigin); // count of 1
EXPECT_TRUE(quota_manager()->IsOriginInUse(kFooOrigin));
quota_manager()->NotifyOriginInUse(kFooOrigin); // count of 2
EXPECT_TRUE(quota_manager()->IsOriginInUse(kFooOrigin));
quota_manager()->NotifyOriginNoLongerInUse(kFooOrigin); // count of 1
EXPECT_TRUE(quota_manager()->IsOriginInUse(kFooOrigin));
EXPECT_FALSE(quota_manager()->IsOriginInUse(kBarOrigin));
quota_manager()->NotifyOriginInUse(kBarOrigin);
EXPECT_TRUE(quota_manager()->IsOriginInUse(kBarOrigin));
quota_manager()->NotifyOriginNoLongerInUse(kBarOrigin);
EXPECT_FALSE(quota_manager()->IsOriginInUse(kBarOrigin));
quota_manager()->NotifyOriginNoLongerInUse(kFooOrigin);
EXPECT_FALSE(quota_manager()->IsOriginInUse(kFooOrigin));
}
TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) {
RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem));
GetPersistentHostQuota("foo.com");
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, quota());
SetPersistentHostQuota("foo.com", 100);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(100, quota());
GetPersistentHostQuota("foo.com");
SetPersistentHostQuota("foo.com", 200);
GetPersistentHostQuota("foo.com");
SetPersistentHostQuota("foo.com", QuotaManager::kPerHostPersistentQuotaLimit);
GetPersistentHostQuota("foo.com");
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaManager::kPerHostPersistentQuotaLimit, quota());
// Persistent quota should be capped at the per-host quota limit.
SetPersistentHostQuota("foo.com",
QuotaManager::kPerHostPersistentQuotaLimit + 100);
GetPersistentHostQuota("foo.com");
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaManager::kPerHostPersistentQuotaLimit, quota());
}
TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) {
RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem));
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
EXPECT_EQ(0, quota());
SetPersistentHostQuota("foo.com", 100);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
EXPECT_EQ(100, quota());
// The actual space avaialble is given to 'unlimited' origins as their quota.
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(kAvailableSpaceForApp, quota());
// GetUsageAndQuotaForStorageClient should just return 0 usage and
// kNoLimit quota.
GetUsageAndQuotaForStorageClient(ToOrigin("http://unlimited/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, usage());
EXPECT_EQ(QuotaManager::kNoLimit, quota());
}
TEST_F(QuotaManagerTest, GetQuotaLowAvailableDiskSpace) {
static const MockOriginData kData[] = {
{"http://foo.com/", kTemp, 100000},
{"http://unlimited/", kTemp, 4000000},
};
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
const int kPoolSize = 10000000;
const int kPerHostQuota = kPoolSize / 5;
// Simulating a low available disk space scenario by making
// kMustRemainAvailable 64KB less than GetAvailableDiskSpaceForTest(), which
// means there is 64KB of storage quota that can be used before triggering
// the low available space logic branch in quota_manager.cc. From the
// perspective of QuotaManager, there are 64KB of free space in the temporary
// pool, so it should return (64KB + usage) as quota since the sum is less
// than the default host quota.
const int kMustRemainAvailable =
static_cast<int>(GetAvailableDiskSpaceForTest() - 65536);
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailable);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(100000, usage());
EXPECT_GT(kPerHostQuota, quota());
EXPECT_EQ(65536 + usage(), quota());
}
TEST_F(QuotaManagerTest, GetStaticQuotaLowAvailableDiskSpace) {
// This test is the same as the previous but with the kStaticHostQuota Finch
// feature enabled. In here, we expect the low available space logic branch
// to be ignored. Doing so should have QuotaManager return the same per host
// quota as what is set in QuotaSettings, despite being in a state of low
// available space. Notice the different expectation in the last line of
// each test.
scoped_feature_list_.InitAndEnableFeature(
storage::features::kStaticHostQuota);
static const MockOriginData kData[] = {
{"http://foo.com/", kTemp, 100000},
{"http://unlimited/", kTemp, 4000000},
};
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
const int kPoolSize = 10000000;
const int kPerHostQuota = kPoolSize / 5;
const int kMustRemainAvailable =
static_cast<int>(GetAvailableDiskSpaceForTest() - 65536);
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailable);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(100000, usage());
EXPECT_EQ(kPerHostQuota, quota());
}
TEST_F(QuotaManagerTest, GetSyncableQuota) {
RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem));
// Pre-condition check: available disk space (for testing) is less than
// the default quota for syncable storage.
EXPECT_LE(kAvailableSpaceForApp,
QuotaManager::kSyncableStorageDefaultHostQuota);
// For unlimited origins the quota manager should return
// kAvailableSpaceForApp as syncable quota (because of the pre-condition).
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
GetUsageAndQuotaForWebApps(ToOrigin("http://unlimited/"), kSync);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, usage());
EXPECT_EQ(kAvailableSpaceForApp, quota());
}
TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_MultiOrigins) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 10 },
{ "http://foo.com:8080/", kPerm, 20 },
{ "https://foo.com/", kPerm, 13 },
{ "https://foo.com:8081/", kPerm, 19 },
{ "http://bar.com/", kPerm, 5 },
{ "https://bar.com/", kPerm, 7 },
{ "http://baz.com/", kPerm, 30 },
{ "http://foo.com/", kTemp, 40 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
SetPersistentHostQuota("foo.com", 100);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20 + 13 + 19, usage());
EXPECT_EQ(100, quota());
}
TEST_F(QuotaManagerTest, GetPersistentUsage_WithModify) {
GetUsage_WithModifyTestBody(kPerm);
}
TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_WithAdditionalTasks) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 10 },
{ "http://foo.com:8080/", kPerm, 20 },
{ "http://bar.com/", kPerm, 13 },
{ "http://foo.com/", kTemp, 40 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
SetPersistentHostQuota("foo.com", 100);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20, usage());
EXPECT_EQ(100, quota());
set_additional_callback_count(0);
RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10 + 20, usage());
EXPECT_EQ(2, additional_callback_count());
}
TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_NukeManager) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 10 },
{ "http://foo.com:8080/", kPerm, 20 },
{ "http://bar.com/", kPerm, 13 },
{ "http://foo.com/", kTemp, 40 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
SetPersistentHostQuota("foo.com", 100);
set_additional_callback_count(0);
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
RunAdditionalUsageAndQuotaTask(ToOrigin("http://foo.com/"), kPerm);
RunAdditionalUsageAndQuotaTask(ToOrigin("http://bar.com/"), kPerm);
// Nuke before waiting for callbacks.
set_quota_manager(nullptr);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kErrorAbort, status());
}
TEST_F(QuotaManagerTest, GetUsage_Simple) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 1 },
{ "http://foo.com:1/", kPerm, 20 },
{ "http://bar.com/", kTemp, 300 },
{ "https://buz.com/", kTemp, 4000 },
{ "http://buz.com/", kTemp, 50000 },
{ "http://bar.com:1/", kPerm, 600000 },
{ "http://foo.com/", kTemp, 7000000 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
GetGlobalUsage(kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 1 + 20 + 600000);
EXPECT_EQ(0, unlimited_usage());
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000);
EXPECT_EQ(0, unlimited_usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 1 + 20);
GetHostUsage("buz.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 4000 + 50000);
}
TEST_F(QuotaManagerTest, GetUsage_WithModification) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kPerm, 1 },
{ "http://foo.com:1/", kPerm, 20 },
{ "http://bar.com/", kTemp, 300 },
{ "https://buz.com/", kTemp, 4000 },
{ "http://buz.com/", kTemp, 50000 },
{ "http://bar.com:1/", kPerm, 600000 },
{ "http://foo.com/", kTemp, 7000000 },
};
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
GetGlobalUsage(kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 1 + 20 + 600000);
EXPECT_EQ(0, unlimited_usage());
client->ModifyOriginAndNotify(ToOrigin("http://foo.com/"), kPerm, 80000000);
GetGlobalUsage(kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 1 + 20 + 600000 + 80000000);
EXPECT_EQ(0, unlimited_usage());
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000);
EXPECT_EQ(0, unlimited_usage());
client->ModifyOriginAndNotify(ToOrigin("http://foo.com/"), kTemp, 1);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000 + 1);
EXPECT_EQ(0, unlimited_usage());
GetHostUsage("buz.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 4000 + 50000);
client->ModifyOriginAndNotify(ToOrigin("http://buz.com/"), kTemp, 900000000);
GetHostUsage("buz.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(usage(), 4000 + 50000 + 900000000);
}
TEST_F(QuotaManagerTest, GetUsage_WithDeleteOrigin) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
{ "http://foo.com/", kPerm, 300 },
{ "http://bar.com/", kTemp, 4000 },
};
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_global_tmp = usage();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_host_tmp = usage();
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_host_pers = usage();
DeleteClientOriginData(client, ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_global_tmp - 1, usage());
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_tmp - 1, usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_pers, usage());
}
TEST_F(QuotaManagerTest, GetStorageCapacity) {
GetStorageCapacity();
scoped_task_environment_.RunUntilIdle();
EXPECT_LE(0, total_space());
EXPECT_LE(0, available_space());
}
TEST_F(QuotaManagerTest, EvictOriginData) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
{ "http://foo.com/", kPerm, 300 },
{ "http://bar.com/", kTemp, 4000 },
};
static const MockOriginData kData2[] = {
{ "http://foo.com/", kTemp, 50000 },
{ "http://foo.com:1/", kTemp, 6000 },
{ "http://foo.com/", kPerm, 700 },
{ "https://foo.com/", kTemp, 80 },
{ "http://bar.com/", kTemp, 9 },
};
MockStorageClient* client1 =
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem);
MockStorageClient* client2 =
CreateClient(kData2, base::size(kData2), QuotaClient::kDatabase);
RegisterClient(client1);
RegisterClient(client2);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_global_tmp = usage();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_host_tmp = usage();
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_host_pers = usage();
for (size_t i = 0; i < base::size(kData1); ++i)
quota_manager()->NotifyStorageAccessed(
QuotaClient::kUnknown, url::Origin::Create(GURL(kData1[i].origin)),
kData1[i].type);
for (size_t i = 0; i < base::size(kData2); ++i)
quota_manager()->NotifyStorageAccessed(
QuotaClient::kUnknown, url::Origin::Create(GURL(kData2[i].origin)),
kData2[i].type);
scoped_task_environment_.RunUntilIdle();
EvictOriginData(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
DumpOriginInfoTable();
scoped_task_environment_.RunUntilIdle();
for (const auto& entry : origin_info_entries()) {
if (entry.type == kTemp)
EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec());
}
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_global_tmp - (1 + 50000), usage());
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_tmp - (1 + 50000), usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_pers, usage());
}
TEST_F(QuotaManagerTest, EvictOriginDataHistogram) {
const url::Origin kOrigin = ToOrigin("http://foo.com/");
static const MockOriginData kData[] = {
{"http://foo.com/", kTemp, 1},
};
base::HistogramTester histograms;
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EvictOriginData(kOrigin, kTemp);
scoped_task_environment_.RunUntilIdle();
// Ensure used count and time since access are recorded.
histograms.ExpectTotalCount(
QuotaManager::kEvictedOriginAccessedCountHistogram, 1);
histograms.ExpectBucketCount(
QuotaManager::kEvictedOriginAccessedCountHistogram, 0, 1);
histograms.ExpectTotalCount(
QuotaManager::kEvictedOriginDaysSinceAccessHistogram, 1);
// First eviction has no 'last' time to compare to.
histograms.ExpectTotalCount(
QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram, 0);
client->AddOriginAndNotify(kOrigin, kTemp, 100);
// Change the used count of the origin.
quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, kOrigin, kTemp);
scoped_task_environment_.RunUntilIdle();
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EvictOriginData(kOrigin, kTemp);
scoped_task_environment_.RunUntilIdle();
// The new used count should be logged.
histograms.ExpectTotalCount(
QuotaManager::kEvictedOriginAccessedCountHistogram, 2);
histograms.ExpectBucketCount(
QuotaManager::kEvictedOriginAccessedCountHistogram, 1, 1);
histograms.ExpectTotalCount(
QuotaManager::kEvictedOriginDaysSinceAccessHistogram, 2);
// Second eviction should log a 'time between repeated eviction' sample.
histograms.ExpectTotalCount(
QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram, 1);
client->AddOriginAndNotify(kOrigin, kTemp, 100);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
DeleteOriginFromDatabase(kOrigin, kTemp);
// Deletion from non-eviction source should not log a histogram sample.
histograms.ExpectTotalCount(
QuotaManager::kDaysBetweenRepeatedOriginEvictionsHistogram, 1);
}
TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
{ "http://foo.com/", kPerm, 300 },
{ "http://bar.com/", kTemp, 4000 },
};
static const int kNumberOfTemporaryOrigins = 3;
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_global_tmp = usage();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_host_tmp = usage();
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_host_pers = usage();
for (size_t i = 0; i < base::size(kData); ++i)
NotifyStorageAccessed(client, url::Origin::Create(GURL(kData[i].origin)),
kData[i].type);
scoped_task_environment_.RunUntilIdle();
client->AddOriginToErrorSet(ToOrigin("http://foo.com/"), kTemp);
for (int i = 0;
i < QuotaManager::kThresholdOfErrorsToBeBlacklisted + 1;
++i) {
EvictOriginData(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kErrorInvalidModification, status());
}
DumpOriginInfoTable();
scoped_task_environment_.RunUntilIdle();
bool found_origin_in_database = false;
for (const auto& entry : origin_info_entries()) {
if (entry.type == kTemp && entry.origin == ToOrigin("http://foo.com/")) {
found_origin_in_database = true;
break;
}
}
// The origin "http://foo.com/" should be in the database.
EXPECT_TRUE(found_origin_in_database);
for (size_t i = 0; i < kNumberOfTemporaryOrigins - 1; ++i) {
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_TRUE(eviction_origin().has_value());
// The origin "http://foo.com/" should not be in the LRU list.
EXPECT_NE(std::string("http://foo.com/"),
eviction_origin()->GetURL().spec());
DeleteOriginFromDatabase(*eviction_origin(), kTemp);
scoped_task_environment_.RunUntilIdle();
}
// Now the LRU list must be empty.
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_FALSE(eviction_origin().has_value());
// Deleting origins from the database should not affect the results of the
// following checks.
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_global_tmp, usage());
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_tmp, usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_pers, usage());
}
TEST_F(QuotaManagerTest, GetEvictionRoundInfo) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
{ "http://foo.com/", kPerm, 300 },
{ "http://unlimited/", kTemp, 4000 },
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
const int kPoolSize = 10000000;
const int kPerHostQuota = kPoolSize / 5;
SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
GetEvictionRoundInfo();
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(21, usage());
EXPECT_EQ(kPoolSize, settings().pool_size);
EXPECT_LE(0, available_space());
}
TEST_F(QuotaManagerTest, DeleteHostDataSimple) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 1 },
};
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_global_tmp = usage();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_host_tmp = usage();
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
int64_t predelete_host_pers = usage();
DeleteHostData(std::string(), kTemp, kAllClients);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_global_tmp, usage());
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_tmp, usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_pers, usage());
DeleteHostData("foo.com", kTemp, kAllClients);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_global_tmp - 1, usage());
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_tmp - 1, usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_host_pers, usage());
}
TEST_F(QuotaManagerTest, DeleteHostDataMultiple) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
{ "http://foo.com/", kPerm, 300 },
{ "http://bar.com/", kTemp, 4000 },
};
static const MockOriginData kData2[] = {
{ "http://foo.com/", kTemp, 50000 },
{ "http://foo.com:1/", kTemp, 6000 },
{ "http://foo.com/", kPerm, 700 },
{ "https://foo.com/", kTemp, 80 },
{ "http://bar.com/", kTemp, 9 },
};
MockStorageClient* client1 =
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem);
MockStorageClient* client2 =
CreateClient(kData2, base::size(kData2), QuotaClient::kDatabase);
RegisterClient(client1);
RegisterClient(client2);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_global_tmp = usage();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_foo_tmp = usage();
GetHostUsage("bar.com", kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_bar_tmp = usage();
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_foo_pers = usage();
GetHostUsage("bar.com", kPerm);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_bar_pers = usage();
reset_status_callback_count();
DeleteHostData("foo.com", kTemp, kAllClients);
DeleteHostData("bar.com", kTemp, kAllClients);
DeleteHostData("foo.com", kTemp, kAllClients);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(3, status_callback_count());
DumpOriginInfoTable();
scoped_task_environment_.RunUntilIdle();
for (const auto& entry : origin_info_entries()) {
if (entry.type != kTemp)
continue;
EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec());
EXPECT_NE(std::string("http://foo.com:1/"), entry.origin.GetURL().spec());
EXPECT_NE(std::string("https://foo.com/"), entry.origin.GetURL().spec());
EXPECT_NE(std::string("http://bar.com/"), entry.origin.GetURL().spec());
}
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_global_tmp - (1 + 20 + 4000 + 50000 + 6000 + 80 + 9),
usage());
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - (1 + 20 + 50000 + 6000 + 80), usage());
GetHostUsage("bar.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_bar_tmp - (4000 + 9), usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_pers, usage());
GetHostUsage("bar.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_bar_pers, usage());
}
// Single-run DeleteOriginData cases must be well covered by
// EvictOriginData tests.
TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
{ "http://foo.com:1/", kTemp, 20 },
{ "http://foo.com/", kPerm, 300 },
{ "http://bar.com/", kTemp, 4000 },
};
static const MockOriginData kData2[] = {
{ "http://foo.com/", kTemp, 50000 },
{ "http://foo.com:1/", kTemp, 6000 },
{ "http://foo.com/", kPerm, 700 },
{ "https://foo.com/", kTemp, 80 },
{ "http://bar.com/", kTemp, 9 },
};
MockStorageClient* client1 =
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem);
MockStorageClient* client2 =
CreateClient(kData2, base::size(kData2), QuotaClient::kDatabase);
RegisterClient(client1);
RegisterClient(client2);
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_global_tmp = usage();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_foo_tmp = usage();
GetHostUsage("bar.com", kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_bar_tmp = usage();
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_foo_pers = usage();
GetHostUsage("bar.com", kPerm);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_bar_pers = usage();
for (size_t i = 0; i < base::size(kData1); ++i) {
quota_manager()->NotifyStorageAccessed(
QuotaClient::kUnknown, url::Origin::Create(GURL(kData1[i].origin)),
kData1[i].type);
}
for (size_t i = 0; i < base::size(kData2); ++i) {
quota_manager()->NotifyStorageAccessed(
QuotaClient::kUnknown, url::Origin::Create(GURL(kData2[i].origin)),
kData2[i].type);
}
scoped_task_environment_.RunUntilIdle();
reset_status_callback_count();
DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, kAllClients);
DeleteOriginData(ToOrigin("http://bar.com/"), kTemp, kAllClients);
DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, kAllClients);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(3, status_callback_count());
DumpOriginInfoTable();
scoped_task_environment_.RunUntilIdle();
for (const auto& entry : origin_info_entries()) {
if (entry.type != kTemp)
continue;
EXPECT_NE(std::string("http://foo.com/"), entry.origin.GetURL().spec());
EXPECT_NE(std::string("http://bar.com/"), entry.origin.GetURL().spec());
}
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_global_tmp - (1 + 4000 + 50000 + 9), usage());
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - (1 + 50000), usage());
GetHostUsage("bar.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_bar_tmp - (4000 + 9), usage());
GetHostUsage("foo.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_pers, usage());
GetHostUsage("bar.com", kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_bar_pers, usage());
}
TEST_F(QuotaManagerTest, GetCachedOrigins) {
static const MockOriginData kData[] = {
{ "http://a.com/", kTemp, 1 },
{ "http://a.com:1/", kTemp, 20 },
{ "http://b.com/", kPerm, 300 },
{ "http://c.com/", kTemp, 4000 },
};
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
// TODO(kinuko): Be careful when we add cache pruner.
std::set<url::Origin> origins;
GetCachedOrigins(kTemp, &origins);
EXPECT_TRUE(origins.empty());
GetHostUsage("a.com", kTemp);
scoped_task_environment_.RunUntilIdle();
GetCachedOrigins(kTemp, &origins);
EXPECT_EQ(2U, origins.size());
GetHostUsage("b.com", kTemp);
scoped_task_environment_.RunUntilIdle();
GetCachedOrigins(kTemp, &origins);
EXPECT_EQ(2U, origins.size());
GetHostUsage("c.com", kTemp);
scoped_task_environment_.RunUntilIdle();
GetCachedOrigins(kTemp, &origins);
EXPECT_EQ(3U, origins.size());
GetCachedOrigins(kPerm, &origins);
EXPECT_TRUE(origins.empty());
GetGlobalUsage(kTemp);
scoped_task_environment_.RunUntilIdle();
GetCachedOrigins(kTemp, &origins);
EXPECT_EQ(3U, origins.size());
for (size_t i = 0; i < base::size(kData); ++i) {
if (kData[i].type == kTemp)
EXPECT_TRUE(base::ContainsKey(origins, ToOrigin(kData[i].origin)));
}
}
TEST_F(QuotaManagerTest, NotifyAndLRUOrigin) {
static const MockOriginData kData[] = {
{ "http://a.com/", kTemp, 0 },
{ "http://a.com:1/", kTemp, 0 },
{ "https://a.com/", kTemp, 0 },
{ "http://b.com/", kPerm, 0 }, // persistent
{ "http://c.com/", kTemp, 0 },
};
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
GURL origin;
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_FALSE(eviction_origin().has_value());
NotifyStorageAccessed(client, ToOrigin("http://a.com/"), kTemp);
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ("http://a.com/", eviction_origin()->GetURL().spec());
NotifyStorageAccessed(client, ToOrigin("http://b.com/"), kPerm);
NotifyStorageAccessed(client, ToOrigin("https://a.com/"), kTemp);
NotifyStorageAccessed(client, ToOrigin("http://c.com/"), kTemp);
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ("http://a.com/", eviction_origin()->GetURL().spec());
DeleteOriginFromDatabase(*eviction_origin(), kTemp);
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ("https://a.com/", eviction_origin()->GetURL().spec());
DeleteOriginFromDatabase(*eviction_origin(), kTemp);
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ("http://c.com/", eviction_origin()->GetURL().spec());
}
TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) {
static const MockOriginData kData[] = {
{ "http://a.com/", kTemp, 0 },
{ "http://a.com:1/", kTemp, 0 },
{ "https://a.com/", kTemp, 0 },
{ "http://b.com/", kPerm, 0 }, // persistent
{ "http://c.com/", kTemp, 0 },
};
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
GURL origin;
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_FALSE(eviction_origin().has_value());
NotifyStorageAccessed(client, ToOrigin("http://a.com/"), kTemp);
NotifyStorageAccessed(client, ToOrigin("http://b.com/"), kPerm);
NotifyStorageAccessed(client, ToOrigin("https://a.com/"), kTemp);
NotifyStorageAccessed(client, ToOrigin("http://c.com/"), kTemp);
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(ToOrigin("http://a.com/"), *eviction_origin());
// Notify origin http://a.com is in use.
NotifyOriginInUse(ToOrigin("http://a.com/"));
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(ToOrigin("https://a.com/"), *eviction_origin());
// Notify origin https://a.com is in use while GetEvictionOrigin is running.
GetEvictionOrigin(kTemp);
NotifyOriginInUse(ToOrigin("https://a.com/"));
scoped_task_environment_.RunUntilIdle();
// Post-filtering must have excluded the returned origin, so we will
// see empty result here.
EXPECT_FALSE(eviction_origin().has_value());
// Notify access for http://c.com while GetEvictionOrigin is running.
GetEvictionOrigin(kTemp);
NotifyStorageAccessed(client, ToOrigin("http://c.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
// Post-filtering must have excluded the returned origin, so we will
// see empty result here.
EXPECT_FALSE(eviction_origin().has_value());
NotifyOriginNoLongerInUse(ToOrigin("http://a.com/"));
NotifyOriginNoLongerInUse(ToOrigin("https://a.com/"));
GetEvictionOrigin(kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(ToOrigin("http://a.com/"), *eviction_origin());
}
TEST_F(QuotaManagerTest, GetOriginsModifiedSince) {
static const MockOriginData kData[] = {
{ "http://a.com/", kTemp, 0 },
{ "http://a.com:1/", kTemp, 0 },
{ "https://a.com/", kTemp, 0 },
{ "http://b.com/", kPerm, 0 }, // persistent
{ "http://c.com/", kTemp, 0 },
};
MockStorageClient* client =
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem);
RegisterClient(client);
GetOriginsModifiedSince(kTemp, base::Time());
scoped_task_environment_.RunUntilIdle();
EXPECT_TRUE(modified_origins().empty());
EXPECT_EQ(modified_origins_type(), kTemp);
base::Time time1 = client->IncrementMockTime();
client->ModifyOriginAndNotify(ToOrigin("http://a.com/"), kTemp, 10);
client->ModifyOriginAndNotify(ToOrigin("http://a.com:1/"), kTemp, 10);
client->ModifyOriginAndNotify(ToOrigin("http://b.com/"), kPerm, 10);
base::Time time2 = client->IncrementMockTime();
client->ModifyOriginAndNotify(ToOrigin("https://a.com/"), kTemp, 10);
client->ModifyOriginAndNotify(ToOrigin("http://c.com/"), kTemp, 10);
base::Time time3 = client->IncrementMockTime();
GetOriginsModifiedSince(kTemp, time1);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(4U, modified_origins().size());
EXPECT_EQ(modified_origins_type(), kTemp);
for (size_t i = 0; i < base::size(kData); ++i) {
if (kData[i].type == kTemp)
EXPECT_EQ(1U, modified_origins().count(ToOrigin(kData[i].origin)));
}
GetOriginsModifiedSince(kTemp, time2);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(2U, modified_origins().size());
GetOriginsModifiedSince(kTemp, time3);
scoped_task_environment_.RunUntilIdle();
EXPECT_TRUE(modified_origins().empty());
EXPECT_EQ(modified_origins_type(), kTemp);
client->ModifyOriginAndNotify(ToOrigin("http://a.com/"), kTemp, 10);
GetOriginsModifiedSince(kTemp, time3);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(1U, modified_origins().size());
EXPECT_EQ(1U, modified_origins().count(ToOrigin("http://a.com/")));
EXPECT_EQ(modified_origins_type(), kTemp);
}
TEST_F(QuotaManagerTest, DumpQuotaTable) {
SetPersistentHostQuota("example1.com", 1);
SetPersistentHostQuota("example2.com", 20);
SetPersistentHostQuota("example3.com", 300);
scoped_task_environment_.RunUntilIdle();
DumpQuotaTable();
scoped_task_environment_.RunUntilIdle();
const QuotaTableEntry kEntries[] = {
QuotaTableEntry("example1.com", kPerm, 1),
QuotaTableEntry("example2.com", kPerm, 20),
QuotaTableEntry("example3.com", kPerm, 300),
};
std::set<QuotaTableEntry> entries(kEntries, kEntries + base::size(kEntries));
for (const auto& quota_entry : quota_entries()) {
SCOPED_TRACE(testing::Message() << "host = " << quota_entry.host << ", "
<< "quota = " << quota_entry.quota);
EXPECT_EQ(1u, entries.erase(quota_entry));
}
EXPECT_TRUE(entries.empty());
}
TEST_F(QuotaManagerTest, DumpOriginInfoTable) {
using std::make_pair;
quota_manager()->NotifyStorageAccessed(
QuotaClient::kUnknown, ToOrigin("http://example.com/"), kTemp);
quota_manager()->NotifyStorageAccessed(
QuotaClient::kUnknown, ToOrigin("http://example.com/"), kPerm);
quota_manager()->NotifyStorageAccessed(
QuotaClient::kUnknown, ToOrigin("http://example.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
DumpOriginInfoTable();
scoped_task_environment_.RunUntilIdle();
using TypedOrigin = std::pair<GURL, StorageType>;
using Entry = std::pair<TypedOrigin, int>;
const Entry kEntries[] = {
make_pair(make_pair(GURL("http://example.com/"), kTemp), 1),
make_pair(make_pair(GURL("http://example.com/"), kPerm), 2),
};
std::set<Entry> entries(kEntries, kEntries + base::size(kEntries));
for (const auto& origin_info : origin_info_entries()) {
SCOPED_TRACE(testing::Message()
<< "host = " << origin_info.origin << ", "
<< "type = " << static_cast<int>(origin_info.type) << ", "
<< "used_count = " << origin_info.used_count);
EXPECT_EQ(1u, entries.erase(make_pair(
make_pair(origin_info.origin.GetURL(), origin_info.type),
origin_info.used_count)));
}
EXPECT_TRUE(entries.empty());
}
TEST_F(QuotaManagerTest, QuotaForEmptyHost) {
GetPersistentHostQuota(std::string());
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(0, quota());
SetPersistentHostQuota(std::string(), 10);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kErrorNotSupported, status());
}
TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleOrigin) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
};
static const MockOriginData kData2[] = {
{ "http://foo.com/", kTemp, 2 },
};
static const MockOriginData kData3[] = {
{ "http://foo.com/", kTemp, 4 },
};
static const MockOriginData kData4[] = {
{ "http://foo.com/", kTemp, 8 },
};
MockStorageClient* client1 =
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem);
MockStorageClient* client2 =
CreateClient(kData2, base::size(kData2), QuotaClient::kAppcache);
MockStorageClient* client3 =
CreateClient(kData3, base::size(kData3), QuotaClient::kDatabase);
MockStorageClient* client4 =
CreateClient(kData4, base::size(kData4), QuotaClient::kIndexedDatabase);
RegisterClient(client1);
RegisterClient(client2);
RegisterClient(client3);
RegisterClient(client4);
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_foo_tmp = usage();
DeleteOriginData(ToOrigin("http://foo.com/"), kTemp,
QuotaClient::kFileSystem);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 1, usage());
DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, QuotaClient::kAppcache);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage());
DeleteOriginData(ToOrigin("http://foo.com/"), kTemp, QuotaClient::kDatabase);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage());
DeleteOriginData(ToOrigin("http://foo.com/"), kTemp,
QuotaClient::kIndexedDatabase);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
}
TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleHost) {
static const MockOriginData kData1[] = {
{ "http://foo.com:1111/", kTemp, 1 },
};
static const MockOriginData kData2[] = {
{ "http://foo.com:2222/", kTemp, 2 },
};
static const MockOriginData kData3[] = {
{ "http://foo.com:3333/", kTemp, 4 },
};
static const MockOriginData kData4[] = {
{ "http://foo.com:4444/", kTemp, 8 },
};
MockStorageClient* client1 =
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem);
MockStorageClient* client2 =
CreateClient(kData2, base::size(kData2), QuotaClient::kAppcache);
MockStorageClient* client3 =
CreateClient(kData3, base::size(kData3), QuotaClient::kDatabase);
MockStorageClient* client4 =
CreateClient(kData4, base::size(kData4), QuotaClient::kIndexedDatabase);
RegisterClient(client1);
RegisterClient(client2);
RegisterClient(client3);
RegisterClient(client4);
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_foo_tmp = usage();
DeleteHostData("foo.com", kTemp, QuotaClient::kFileSystem);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 1, usage());
DeleteHostData("foo.com", kTemp, QuotaClient::kAppcache);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage());
DeleteHostData("foo.com", kTemp, QuotaClient::kDatabase);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage());
DeleteHostData("foo.com", kTemp, QuotaClient::kIndexedDatabase);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
}
TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleOrigin) {
static const MockOriginData kData1[] = {
{ "http://foo.com/", kTemp, 1 },
};
static const MockOriginData kData2[] = {
{ "http://foo.com/", kTemp, 2 },
};
static const MockOriginData kData3[] = {
{ "http://foo.com/", kTemp, 4 },
};
static const MockOriginData kData4[] = {
{ "http://foo.com/", kTemp, 8 },
};
MockStorageClient* client1 =
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem);
MockStorageClient* client2 =
CreateClient(kData2, base::size(kData2), QuotaClient::kAppcache);
MockStorageClient* client3 =
CreateClient(kData3, base::size(kData3), QuotaClient::kDatabase);
MockStorageClient* client4 =
CreateClient(kData4, base::size(kData4), QuotaClient::kIndexedDatabase);
RegisterClient(client1);
RegisterClient(client2);
RegisterClient(client3);
RegisterClient(client4);
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_foo_tmp = usage();
DeleteOriginData(ToOrigin("http://foo.com/"), kTemp,
QuotaClient::kFileSystem | QuotaClient::kDatabase);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 4 - 1, usage());
DeleteOriginData(ToOrigin("http://foo.com/"), kTemp,
QuotaClient::kAppcache | QuotaClient::kIndexedDatabase);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
}
TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleHost) {
static const MockOriginData kData1[] = {
{ "http://foo.com:1111/", kTemp, 1 },
};
static const MockOriginData kData2[] = {
{ "http://foo.com:2222/", kTemp, 2 },
};
static const MockOriginData kData3[] = {
{ "http://foo.com:3333/", kTemp, 4 },
};
static const MockOriginData kData4[] = {
{ "http://foo.com:4444/", kTemp, 8 },
};
MockStorageClient* client1 =
CreateClient(kData1, base::size(kData1), QuotaClient::kFileSystem);
MockStorageClient* client2 =
CreateClient(kData2, base::size(kData2), QuotaClient::kAppcache);
MockStorageClient* client3 =
CreateClient(kData3, base::size(kData3), QuotaClient::kDatabase);
MockStorageClient* client4 =
CreateClient(kData4, base::size(kData4), QuotaClient::kIndexedDatabase);
RegisterClient(client1);
RegisterClient(client2);
RegisterClient(client3);
RegisterClient(client4);
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
const int64_t predelete_foo_tmp = usage();
DeleteHostData("foo.com", kTemp,
QuotaClient::kFileSystem | QuotaClient::kAppcache);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage());
DeleteHostData("foo.com", kTemp,
QuotaClient::kDatabase | QuotaClient::kIndexedDatabase);
scoped_task_environment_.RunUntilIdle();
GetHostUsage("foo.com", kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
}
TEST_F(QuotaManagerTest, GetUsageAndQuota_Incognito) {
ResetQuotaManager(true);
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com/", kPerm, 80 },
};
RegisterClient(
CreateClient(kData, base::size(kData), QuotaClient::kFileSystem));
// Query global usage to warmup the usage tracker caching.
GetGlobalUsage(kTemp);
GetGlobalUsage(kPerm);
scoped_task_environment_.RunUntilIdle();
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(80, usage());
EXPECT_EQ(0, quota());
const int kPoolSize = 1000;
const int kPerHostQuota = kPoolSize / 5;
SetQuotaSettings(kPoolSize, kPerHostQuota, INT64_C(0));
GetStorageCapacity();
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(kPoolSize, total_space());
EXPECT_EQ(kPoolSize - 80 - 10, available_space());
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10, usage());
EXPECT_LE(kPerHostQuota, quota());
mock_special_storage_policy()->AddUnlimited(GURL("http://foo.com/"));
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(80, usage());
EXPECT_EQ(available_space() + usage(), quota());
GetUsageAndQuotaForWebApps(ToOrigin("http://foo.com/"), kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(QuotaStatusCode::kOk, status());
EXPECT_EQ(10, usage());
EXPECT_EQ(available_space() + usage(), quota());
}
TEST_F(QuotaManagerTest, GetUsageAndQuota_SessionOnly) {
const url::Origin kEpheremalOrigin = ToOrigin("http://ephemeral/");
mock_special_storage_policy()->AddSessionOnly(kEpheremalOrigin.GetURL());
GetUsageAndQuotaForWebApps(kEpheremalOrigin, kTemp);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(quota_manager()->settings().session_only_per_host_quota, quota());
GetUsageAndQuotaForWebApps(kEpheremalOrigin, kPerm);
scoped_task_environment_.RunUntilIdle();
EXPECT_EQ(0, quota());
}
} // namespace content