Commit 113cf261 authored by tzik@chromium.org's avatar tzik@chromium.org

[Quota] Add UsageTracker::GetGlobalLimitedUsage.

This CL add GetGlobalLimitedUsage to UsageTracker and
replace GetGlobalUsage in QuotaManager with limited usage version.

BUG=220029
TEST=existing test should keep green

Review URL: https://chromiumcodereview.appspot.com/15907004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202540 0039d316-1c4b-4281-b951-d872f2087c98
parent affb228b
...@@ -191,19 +191,17 @@ int64 CallSystemGetAmountOfFreeDiskSpace(const base::FilePath& profile_path) { ...@@ -191,19 +191,17 @@ int64 CallSystemGetAmountOfFreeDiskSpace(const base::FilePath& profile_path) {
return base::SysInfo::AmountOfFreeDiskSpace(profile_path); return base::SysInfo::AmountOfFreeDiskSpace(profile_path);
} }
int64 CalculateTemporaryGlobalQuota(int64 global_usage, int64 CalculateTemporaryGlobalQuota(int64 global_limited_usage,
int64 global_unlimited_usage,
int64 available_space) { int64 available_space) {
DCHECK_GE(global_usage, global_unlimited_usage); DCHECK_GE(global_limited_usage, 0);
int64 limited_usage = global_usage - global_unlimited_usage; int64 avail_space = available_space;
int64 avail_space = available_space; if (avail_space < kint64max - global_limited_usage) {
if (avail_space < kint64max - limited_usage) { // We basically calculate the temporary quota by
// We basically calculate the temporary quota by // [available_space + space_used_for_temp] * kTempQuotaRatio,
// [available_space + space_used_for_temp] * kTempQuotaRatio, // but make sure we'll have no overflow.
// but make sure we'll have no overflow. avail_space += global_limited_usage;
avail_space += limited_usage; }
} return avail_space * kTemporaryQuotaRatioToAvail;
return avail_space * kTemporaryQuotaRatioToAvail;
} }
void DispatchTemporaryGlobalQuotaCallback( void DispatchTemporaryGlobalQuotaCallback(
...@@ -216,8 +214,7 @@ void DispatchTemporaryGlobalQuotaCallback( ...@@ -216,8 +214,7 @@ void DispatchTemporaryGlobalQuotaCallback(
} }
callback.Run(status, CalculateTemporaryGlobalQuota( callback.Run(status, CalculateTemporaryGlobalQuota(
usage_and_quota.global_usage, usage_and_quota.global_limited_usage,
usage_and_quota.global_unlimited_usage,
usage_and_quota.available_disk_space)); usage_and_quota.available_disk_space));
} }
...@@ -238,14 +235,12 @@ int64 CalculateQuotaWithDiskSpace( ...@@ -238,14 +235,12 @@ int64 CalculateQuotaWithDiskSpace(
int64 CalculateTemporaryHostQuota(int64 host_usage, int64 CalculateTemporaryHostQuota(int64 host_usage,
int64 global_quota, int64 global_quota,
int64 global_usage, int64 global_limited_usage) {
int64 global_unlimited_usage) { DCHECK_GE(global_limited_usage, 0);
DCHECK_GE(global_usage, global_unlimited_usage); int64 host_quota = global_quota / QuotaManager::kPerHostTemporaryPortion;
int64 limited_global_usage = global_usage - global_unlimited_usage; if (global_limited_usage > global_quota)
int64 host_quota = global_quota / QuotaManager::kPerHostTemporaryPortion; host_quota = std::min(host_quota, host_usage);
if (limited_global_usage > global_quota) return host_quota;
host_quota = std::min(host_quota, host_usage);
return host_quota;
} }
void DispatchUsageAndQuotaForWebApps( void DispatchUsageAndQuotaForWebApps(
...@@ -264,11 +259,9 @@ void DispatchUsageAndQuotaForWebApps( ...@@ -264,11 +259,9 @@ void DispatchUsageAndQuotaForWebApps(
int64 usage = usage_and_quota.usage; int64 usage = usage_and_quota.usage;
int64 quota = usage_and_quota.quota; int64 quota = usage_and_quota.quota;
if (type == kStorageTypeTemporary) { if (type == kStorageTypeTemporary && !is_unlimited) {
quota = CalculateTemporaryHostQuota( quota = CalculateTemporaryHostQuota(
usage, quota, usage, quota, usage_and_quota.global_limited_usage);
usage_and_quota.global_usage,
usage_and_quota.global_unlimited_usage);
} }
if (is_incognito) { if (is_incognito) {
...@@ -297,21 +290,18 @@ void DispatchUsageAndQuotaForWebApps( ...@@ -297,21 +290,18 @@ void DispatchUsageAndQuotaForWebApps(
UsageAndQuota::UsageAndQuota() UsageAndQuota::UsageAndQuota()
: usage(0), : usage(0),
global_usage(0), global_limited_usage(0),
global_unlimited_usage(0),
quota(0), quota(0),
available_disk_space(0) { available_disk_space(0) {
} }
UsageAndQuota::UsageAndQuota( UsageAndQuota::UsageAndQuota(
int64 usage, int64 usage,
int64 global_usage, int64 global_limited_usage,
int64 global_unlimited_usage,
int64 quota, int64 quota,
int64 available_disk_space) int64 available_disk_space)
: usage(usage), : usage(usage),
global_usage(global_usage), global_limited_usage(global_limited_usage),
global_unlimited_usage(global_unlimited_usage),
quota(quota), quota(quota),
available_disk_space(available_disk_space) { available_disk_space(available_disk_space) {
} }
...@@ -323,11 +313,11 @@ class UsageAndQuotaCallbackDispatcher ...@@ -323,11 +313,11 @@ class UsageAndQuotaCallbackDispatcher
UsageAndQuotaCallbackDispatcher(QuotaManager* manager) UsageAndQuotaCallbackDispatcher(QuotaManager* manager)
: QuotaTask(manager), : QuotaTask(manager),
has_usage_(false), has_usage_(false),
has_global_usage_(false), has_global_limited_usage_(false),
has_quota_(false), has_quota_(false),
has_available_disk_space_(false), has_available_disk_space_(false),
status_(kQuotaStatusUnknown), status_(kQuotaStatusUnknown),
usage_and_quota_(-1, -1, -1, -1, -1), usage_and_quota_(-1, -1, -1, -1),
waiting_callbacks_(1) {} waiting_callbacks_(1) {}
virtual ~UsageAndQuotaCallbackDispatcher() {} virtual ~UsageAndQuotaCallbackDispatcher() {}
...@@ -342,14 +332,9 @@ class UsageAndQuotaCallbackDispatcher ...@@ -342,14 +332,9 @@ class UsageAndQuotaCallbackDispatcher
has_usage_ = true; has_usage_ = true;
} }
void set_global_usage(int64 global_usage) { void set_global_limited_usage(int64 global_limited_usage) {
usage_and_quota_.global_usage = global_usage; usage_and_quota_.global_limited_usage = global_limited_usage;
has_global_usage_ = true; has_global_limited_usage_ = true;
}
void set_global_unlimited_usage(int64 global_unlimited_usage) {
usage_and_quota_.global_unlimited_usage = global_unlimited_usage;
has_global_usage_ = true;
} }
void set_quota(int64 quota) { void set_quota(int64 quota) {
...@@ -369,11 +354,12 @@ class UsageAndQuotaCallbackDispatcher ...@@ -369,11 +354,12 @@ class UsageAndQuotaCallbackDispatcher
AsWeakPtr()); AsWeakPtr());
} }
GlobalUsageCallback GetGlobalUsageCallback() { UsageCallback GetGlobalLimitedUsageCallback() {
++waiting_callbacks_; ++waiting_callbacks_;
has_global_usage_ = true; has_global_limited_usage_ = true;
return base::Bind(&UsageAndQuotaCallbackDispatcher::DidGetGlobalUsage, return base::Bind(
AsWeakPtr()); &UsageAndQuotaCallbackDispatcher::DidGetGlobalLimitedUsage,
AsWeakPtr());
} }
QuotaCallback GetQuotaCallback() { QuotaCallback GetQuotaCallback() {
...@@ -398,12 +384,10 @@ class UsageAndQuotaCallbackDispatcher ...@@ -398,12 +384,10 @@ class UsageAndQuotaCallbackDispatcher
CheckCompleted(); CheckCompleted();
} }
void DidGetGlobalUsage(int64 usage, void DidGetGlobalLimitedUsage(int64 limited_usage) {
int64 unlimited_usage) {
if (status_ == kQuotaStatusUnknown) if (status_ == kQuotaStatusUnknown)
status_ = kQuotaStatusOk; status_ = kQuotaStatusOk;
usage_and_quota_.global_usage = usage; usage_and_quota_.global_limited_usage = limited_usage;
usage_and_quota_.global_unlimited_usage = unlimited_usage;
CheckCompleted(); CheckCompleted();
} }
...@@ -436,10 +420,8 @@ class UsageAndQuotaCallbackDispatcher ...@@ -436,10 +420,8 @@ class UsageAndQuotaCallbackDispatcher
virtual void Completed() OVERRIDE { virtual void Completed() OVERRIDE {
DCHECK(!has_usage_ || usage_and_quota_.usage >= 0); DCHECK(!has_usage_ || usage_and_quota_.usage >= 0);
DCHECK_LE(usage_and_quota_.global_unlimited_usage, DCHECK(!has_global_limited_usage_ ||
usage_and_quota_.global_usage); usage_and_quota_.global_limited_usage >= 0);
DCHECK(!has_global_usage_ ||
usage_and_quota_.global_unlimited_usage >= 0);
DCHECK(!has_quota_ || usage_and_quota_.quota >= 0); DCHECK(!has_quota_ || usage_and_quota_.quota >= 0);
DCHECK(!has_available_disk_space_ || DCHECK(!has_available_disk_space_ ||
usage_and_quota_.available_disk_space >= 0); usage_and_quota_.available_disk_space >= 0);
...@@ -455,7 +437,7 @@ class UsageAndQuotaCallbackDispatcher ...@@ -455,7 +437,7 @@ class UsageAndQuotaCallbackDispatcher
// For sanity checks, they're checked only when DCHECK is on. // For sanity checks, they're checked only when DCHECK is on.
bool has_usage_; bool has_usage_;
bool has_global_usage_; bool has_global_limited_usage_;
bool has_quota_; bool has_quota_;
bool has_available_disk_space_; bool has_available_disk_space_;
...@@ -858,8 +840,8 @@ void QuotaManager::GetUsageAndQuotaForWebApps( ...@@ -858,8 +840,8 @@ void QuotaManager::GetUsageAndQuotaForWebApps(
dispatcher->set_quota(kNoLimit); dispatcher->set_quota(kNoLimit);
} else { } else {
if (type == kStorageTypeTemporary) { if (type == kStorageTypeTemporary) {
GetUsageTracker(type)->GetGlobalUsage( GetUsageTracker(type)->GetGlobalLimitedUsage(
dispatcher->GetGlobalUsageCallback()); dispatcher->GetGlobalLimitedUsageCallback());
GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback()); GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback());
} else if (type == kStorageTypePersistent) { } else if (type == kStorageTypePersistent) {
GetPersistentHostQuota(net::GetHostOrSpecFromURL(origin), GetPersistentHostQuota(net::GetHostOrSpecFromURL(origin),
...@@ -990,8 +972,8 @@ void QuotaManager::GetTemporaryGlobalQuota(const QuotaCallback& callback) { ...@@ -990,8 +972,8 @@ void QuotaManager::GetTemporaryGlobalQuota(const QuotaCallback& callback) {
UsageAndQuotaCallbackDispatcher* dispatcher = UsageAndQuotaCallbackDispatcher* dispatcher =
new UsageAndQuotaCallbackDispatcher(this); new UsageAndQuotaCallbackDispatcher(this);
GetGlobalUsage(kStorageTypeTemporary, GetUsageTracker(kStorageTypeTemporary)->
dispatcher->GetGlobalUsageCallback()); GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback());
GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); GetAvailableSpace(dispatcher->GetAvailableSpaceCallback());
dispatcher->WaitForResults( dispatcher->WaitForResults(
base::Bind(&DispatchTemporaryGlobalQuotaCallback, callback)); base::Bind(&DispatchTemporaryGlobalQuotaCallback, callback));
...@@ -1450,11 +1432,12 @@ void QuotaManager::EvictOriginData( ...@@ -1450,11 +1432,12 @@ void QuotaManager::EvictOriginData(
void QuotaManager::GetUsageAndQuotaForEviction( void QuotaManager::GetUsageAndQuotaForEviction(
const UsageAndQuotaCallback& callback) { const UsageAndQuotaCallback& callback) {
DCHECK(io_thread_->BelongsToCurrentThread()); DCHECK(io_thread_->BelongsToCurrentThread());
LazyInitialize();
UsageAndQuotaCallbackDispatcher* dispatcher = UsageAndQuotaCallbackDispatcher* dispatcher =
new UsageAndQuotaCallbackDispatcher(this); new UsageAndQuotaCallbackDispatcher(this);
GetGlobalUsage(kStorageTypeTemporary, GetUsageTracker(kStorageTypeTemporary)->
dispatcher->GetGlobalUsageCallback()); GetGlobalLimitedUsage(dispatcher->GetGlobalLimitedUsageCallback());
GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback()); GetTemporaryGlobalQuota(dispatcher->GetQuotaCallback());
GetAvailableSpace(dispatcher->GetAvailableSpaceCallback()); GetAvailableSpace(dispatcher->GetAvailableSpaceCallback());
dispatcher->WaitForResults(callback); dispatcher->WaitForResults(callback);
......
...@@ -48,15 +48,13 @@ struct QuotaManagerDeleter; ...@@ -48,15 +48,13 @@ struct QuotaManagerDeleter;
struct WEBKIT_STORAGE_EXPORT UsageAndQuota { struct WEBKIT_STORAGE_EXPORT UsageAndQuota {
int64 usage; int64 usage;
int64 global_usage; int64 global_limited_usage;
int64 global_unlimited_usage;
int64 quota; int64 quota;
int64 available_disk_space; int64 available_disk_space;
UsageAndQuota(); UsageAndQuota();
UsageAndQuota(int64 usage, UsageAndQuota(int64 usage,
int64 global_usage, int64 global_limited_usage,
int64 global_unlimited_usage,
int64 quota, int64 quota,
int64 available_disk_space); int64 available_disk_space);
}; };
......
...@@ -346,8 +346,7 @@ class QuotaManagerTest : public testing::Test { ...@@ -346,8 +346,7 @@ class QuotaManagerTest : public testing::Test {
void DidGetUsageAndQuotaForEviction(QuotaStatusCode status, void DidGetUsageAndQuotaForEviction(QuotaStatusCode status,
const UsageAndQuota& usage_and_quota) { const UsageAndQuota& usage_and_quota) {
quota_status_ = status; quota_status_ = status;
usage_ = usage_and_quota.global_usage; limited_usage_ = usage_and_quota.global_limited_usage;
unlimited_usage_ = usage_and_quota.global_unlimited_usage;
quota_ = usage_and_quota.quota; quota_ = usage_and_quota.quota;
available_space_ = usage_and_quota.available_disk_space; available_space_ = usage_and_quota.available_disk_space;
} }
...@@ -390,6 +389,7 @@ class QuotaManagerTest : public testing::Test { ...@@ -390,6 +389,7 @@ class QuotaManagerTest : public testing::Test {
QuotaStatusCode status() const { return quota_status_; } QuotaStatusCode status() const { return quota_status_; }
const UsageInfoEntries& usage_info() const { return usage_info_; } const UsageInfoEntries& usage_info() const { return usage_info_; }
int64 usage() const { return usage_; } int64 usage() const { return usage_; }
int64 limited_usage() const { return limited_usage_; }
int64 unlimited_usage() const { return unlimited_usage_; } int64 unlimited_usage() const { return unlimited_usage_; }
int64 quota() const { return quota_; } int64 quota() const { return quota_; }
int64 available_space() const { return available_space_; } int64 available_space() const { return available_space_; }
...@@ -420,6 +420,7 @@ class QuotaManagerTest : public testing::Test { ...@@ -420,6 +420,7 @@ class QuotaManagerTest : public testing::Test {
QuotaStatusCode quota_status_; QuotaStatusCode quota_status_;
UsageInfoEntries usage_info_; UsageInfoEntries usage_info_;
int64 usage_; int64 usage_;
int64 limited_usage_;
int64 unlimited_usage_; int64 unlimited_usage_;
int64 quota_; int64 quota_;
int64 available_space_; int64 available_space_;
...@@ -1411,8 +1412,7 @@ TEST_F(QuotaManagerTest, GetUsageAndQuotaForEviction) { ...@@ -1411,8 +1412,7 @@ TEST_F(QuotaManagerTest, GetUsageAndQuotaForEviction) {
GetUsageAndQuotaForEviction(); GetUsageAndQuotaForEviction();
base::MessageLoop::current()->RunUntilIdle(); base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(kQuotaStatusOk, status()); EXPECT_EQ(kQuotaStatusOk, status());
EXPECT_EQ(4021, usage()); EXPECT_EQ(21, limited_usage());
EXPECT_EQ(4000, unlimited_usage());
EXPECT_EQ(10000000, quota()); EXPECT_EQ(10000000, quota());
EXPECT_LE(0, available_space()); EXPECT_LE(0, available_space());
} }
......
...@@ -166,10 +166,8 @@ void QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction( ...@@ -166,10 +166,8 @@ void QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction(
const UsageAndQuota& qau) { const UsageAndQuota& qau) {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
// unlimited_usage is a subset of usage int64 usage = qau.global_limited_usage;
DCHECK_GE(qau.global_usage, qau.global_unlimited_usage); DCHECK_GE(usage, 0);
int64 usage = qau.global_usage - qau.global_unlimited_usage;
if (status != kQuotaStatusOk) if (status != kQuotaStatusOk)
++statistics_.num_errors_on_getting_usage_and_quota; ++statistics_.num_errors_on_getting_usage_and_quota;
......
...@@ -27,7 +27,6 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler { ...@@ -27,7 +27,6 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler {
public: public:
explicit MockQuotaEvictionHandler(QuotaTemporaryStorageEvictorTest *test) explicit MockQuotaEvictionHandler(QuotaTemporaryStorageEvictorTest *test)
: quota_(0), : quota_(0),
unlimited_usage_(0),
available_space_(0), available_space_(0),
error_on_evict_origin_data_(false), error_on_evict_origin_data_(false),
error_on_get_usage_and_quota_(false) {} error_on_get_usage_and_quota_(false) {}
...@@ -54,8 +53,7 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler { ...@@ -54,8 +53,7 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler {
} }
if (!task_for_get_usage_and_quota_.is_null()) if (!task_for_get_usage_and_quota_.is_null())
task_for_get_usage_and_quota_.Run(); task_for_get_usage_and_quota_.Run();
UsageAndQuota quota_and_usage( UsageAndQuota quota_and_usage(-1, GetUsage(), quota_, available_space_);
0, GetUsage(), unlimited_usage_, quota_, available_space_);
callback.Run(quota::kQuotaStatusOk, quota_and_usage); callback.Run(quota::kQuotaStatusOk, quota_and_usage);
} }
...@@ -80,9 +78,6 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler { ...@@ -80,9 +78,6 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler {
void set_quota(int64 quota) { void set_quota(int64 quota) {
quota_ = quota; quota_ = quota;
} }
void set_unlimited_usage(int64 usage) {
unlimited_usage_ = usage;
}
void set_available_space(int64 available_space) { void set_available_space(int64 available_space) {
available_space_ = available_space; available_space_ = available_space;
} }
...@@ -127,7 +122,6 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler { ...@@ -127,7 +122,6 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler {
} }
int64 quota_; int64 quota_;
int64 unlimited_usage_;
int64 available_space_; int64 available_space_;
std::list<GURL> origin_order_; std::list<GURL> origin_order_;
std::map<GURL, int64> origins_; std::map<GURL, int64> origins_;
...@@ -413,19 +407,4 @@ TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) { ...@@ -413,19 +407,4 @@ TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) {
EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); EXPECT_EQ(0, statistics().num_skipped_eviction_rounds);
} }
TEST_F(QuotaTemporaryStorageEvictorTest, UnlimitedExclusionEvictionTest) {
quota_eviction_handler()->AddOrigin(GURL("http://www.z.com"), 3000);
quota_eviction_handler()->AddOrigin(GURL("http://www.y.com"), 200);
quota_eviction_handler()->AddOrigin(GURL("http://www.x.com"), 500000);
quota_eviction_handler()->set_unlimited_usage(500000);
quota_eviction_handler()->set_quota(5000);
quota_eviction_handler()->set_available_space(1000000000);
EXPECT_EQ(3000 + 200 + 500000, quota_eviction_handler()->GetUsage());
set_repeated_eviction(false);
temporary_storage_evictor()->Start();
base::MessageLoop::current()->RunUntilIdle();
// Nothing should have been evicted.
EXPECT_EQ(3000 + 200 + 500000, quota_eviction_handler()->GetUsage());
}
} // namespace quota } // namespace quota
...@@ -60,6 +60,12 @@ bool OriginSetContainsOrigin(const OriginSetByHost& origins, ...@@ -60,6 +60,12 @@ bool OriginSetContainsOrigin(const OriginSetByHost& origins,
return itr != origins.end() && ContainsKey(itr->second, origin); return itr != origins.end() && ContainsKey(itr->second, origin);
} }
void DidGetGlobalUsageForLimitedGlobalUsage(const UsageCallback& callback,
int64 total_global_usage,
int64 global_unlimited_usage) {
callback.Run(total_global_usage - global_unlimited_usage);
}
} // namespace } // namespace
// UsageTracker ---------------------------------------------------------- // UsageTracker ----------------------------------------------------------
...@@ -88,6 +94,10 @@ ClientUsageTracker* UsageTracker::GetClientTracker(QuotaClient::ID client_id) { ...@@ -88,6 +94,10 @@ ClientUsageTracker* UsageTracker::GetClientTracker(QuotaClient::ID client_id) {
return NULL; return NULL;
} }
void UsageTracker::GetGlobalLimitedUsage(const UsageCallback& callback) {
GetGlobalUsage(base::Bind(&DidGetGlobalUsageForLimitedGlobalUsage, callback));
}
void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) { void UsageTracker::GetGlobalUsage(const GlobalUsageCallback& callback) {
if (!global_usage_callbacks_.Add(callback)) if (!global_usage_callbacks_.Add(callback))
return; return;
......
...@@ -36,6 +36,7 @@ class WEBKIT_STORAGE_EXPORT UsageTracker : public QuotaTaskObserver { ...@@ -36,6 +36,7 @@ class WEBKIT_STORAGE_EXPORT UsageTracker : public QuotaTaskObserver {
StorageType type() const { return type_; } StorageType type() const { return type_; }
ClientUsageTracker* GetClientTracker(QuotaClient::ID client_id); ClientUsageTracker* GetClientTracker(QuotaClient::ID client_id);
void GetGlobalLimitedUsage(const UsageCallback& callback);
void GetGlobalUsage(const GlobalUsageCallback& callback); void GetGlobalUsage(const GlobalUsageCallback& callback);
void GetHostUsage(const std::string& host, const UsageCallback& callback); void GetHostUsage(const std::string& host, const UsageCallback& callback);
void UpdateUsageCache(QuotaClient::ID client_id, void UpdateUsageCache(QuotaClient::ID client_id,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment