summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-17 14:15:17 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-17 14:15:17 +0000
commit1de3cc5c2349e22d9e755ddad520733ed5f7cb73 (patch)
treeb3ea0438ae9ff502d14ee631f51c3f2d30602cd5 /webkit
parente875094dcb290ade336d474aed96c7021b26d43a (diff)
downloadchromium_src-1de3cc5c2349e22d9e755ddad520733ed5f7cb73.zip
chromium_src-1de3cc5c2349e22d9e755ddad520733ed5f7cb73.tar.gz
chromium_src-1de3cc5c2349e22d9e755ddad520733ed5f7cb73.tar.bz2
Revert 105791 (to see if it fixes browser_tests) - Change default global temporary quota limit to 50% of available space
BUG=94363 TEST=test_shell_tests:Quota* Review URL: http://codereview.chromium.org/7806014 TBR=kinuko@chromium.org Review URL: http://codereview.chromium.org/8319004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105800 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/quota/quota_database.cc28
-rw-r--r--webkit/quota/quota_database.h8
-rw-r--r--webkit/quota/quota_database_unittest.cc44
-rw-r--r--webkit/quota/quota_manager.cc623
-rw-r--r--webkit/quota/quota_manager.h91
-rw-r--r--webkit/quota/quota_manager_unittest.cc55
-rw-r--r--webkit/quota/quota_temporary_storage_evictor.cc36
-rw-r--r--webkit/quota/quota_temporary_storage_evictor.h11
-rw-r--r--webkit/quota/quota_temporary_storage_evictor_unittest.cc12
-rw-r--r--webkit/tools/test_shell/test_shell.gypi6
10 files changed, 454 insertions, 460 deletions
diff --git a/webkit/quota/quota_database.cc b/webkit/quota/quota_database.cc
index 0563535..d34451e 100644
--- a/webkit/quota/quota_database.cc
+++ b/webkit/quota/quota_database.cc
@@ -23,11 +23,12 @@ namespace {
// Definitions for database schema.
-const int kCurrentVersion = 4;
+const int kCurrentVersion = 3;
const int kCompatibleVersion = 2;
const char kHostQuotaTable[] = "HostQuotaTable";
const char kOriginInfoTable[] = "OriginInfoTable";
+const char kGlobalQuotaKeyPrefix[] = "GlobalQuota-";
const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped";
class HistogramUniquifier {
@@ -47,10 +48,13 @@ bool PrepareCachedStatement(
return true;
}
-bool VerifyValidQuotaConfig(const char* key) {
- return (key != NULL &&
- (!strcmp(key, QuotaDatabase::kDesiredAvailableSpaceKey) ||
- !strcmp(key, QuotaDatabase::kTemporaryQuotaOverrideKey)));
+std::string GetGlobalQuotaKey(quota::StorageType type) {
+ if (type == quota::kStorageTypeTemporary)
+ return std::string(kGlobalQuotaKeyPrefix) + "temporary";
+ else if (type == quota::kStorageTypePersistent)
+ return std::string(kGlobalQuotaKeyPrefix) + "persistent";
+ NOTREACHED() << "Unknown storage type " << type;
+ return std::string();
}
const int kCommitIntervalMs = 30000;
@@ -58,10 +62,6 @@ const int kCommitIntervalMs = 30000;
} // anonymous namespace
// static
-const char QuotaDatabase::kDesiredAvailableSpaceKey[] = "DesiredAvailableSpace";
-const char QuotaDatabase::kTemporaryQuotaOverrideKey[] =
- "TemporaryQuotaOverride";
-
const QuotaDatabase::TableSchema QuotaDatabase::kTables[] = {
{ kHostQuotaTable,
"(host TEXT NOT NULL,"
@@ -334,18 +334,16 @@ bool QuotaDatabase::DeleteOriginInfo(
return true;
}
-bool QuotaDatabase::GetQuotaConfigValue(const char* key, int64* value) {
+bool QuotaDatabase::GetGlobalQuota(StorageType type, int64* quota) {
if (!LazyOpen(false))
return false;
- DCHECK(VerifyValidQuotaConfig(key));
- return meta_table_->GetValue(key, value);
+ return meta_table_->GetValue(GetGlobalQuotaKey(type).c_str(), quota);
}
-bool QuotaDatabase::SetQuotaConfigValue(const char* key, int64 value) {
+bool QuotaDatabase::SetGlobalQuota(StorageType type, int64 quota) {
if (!LazyOpen(true))
return false;
- DCHECK(VerifyValidQuotaConfig(key));
- return meta_table_->SetValue(key, value);
+ return meta_table_->SetValue(GetGlobalQuotaKey(type).c_str(), quota);
}
bool QuotaDatabase::GetLRUOrigin(
diff --git a/webkit/quota/quota_database.h b/webkit/quota/quota_database.h
index 7a816f6..ec437f1 100644
--- a/webkit/quota/quota_database.h
+++ b/webkit/quota/quota_database.h
@@ -33,10 +33,6 @@ class SpecialStoragePolicy;
// All the methods of this class must run on the DB thread.
class QuotaDatabase {
public:
- // Constants for {Get,Set}QuotaConfigValue keys.
- static const char kDesiredAvailableSpaceKey[];
- static const char kTemporaryQuotaOverrideKey[];
-
// If 'path' is empty, an in memory database will be used.
explicit QuotaDatabase(const FilePath& path);
~QuotaDatabase();
@@ -63,8 +59,8 @@ class QuotaDatabase {
bool DeleteOriginInfo(const GURL& origin, StorageType type);
- bool GetQuotaConfigValue(const char* key, int64* value);
- bool SetQuotaConfigValue(const char* key, int64 value);
+ bool GetGlobalQuota(StorageType type, int64* quota);
+ bool SetGlobalQuota(StorageType type, int64 quota);
// Sets |origin| to the least recently used origin of origins not included
// in |exceptions| and not granted the special unlimited storage right.
diff --git a/webkit/quota/quota_database_unittest.cc b/webkit/quota/quota_database_unittest.cc
index 7045f7f..05001a7 100644
--- a/webkit/quota/quota_database_unittest.cc
+++ b/webkit/quota/quota_database_unittest.cc
@@ -106,30 +106,26 @@ class QuotaDatabaseTest : public testing::Test {
QuotaDatabase db(kDbFile);
ASSERT_TRUE(db.LazyOpen(true));
- const char* kTempQuotaKey = QuotaDatabase::kTemporaryQuotaOverrideKey;
- const char* kAvailSpaceKey = QuotaDatabase::kDesiredAvailableSpaceKey;
-
- int64 value = 0;
- const int64 kValue1 = 456;
- const int64 kValue2 = 123000;
- EXPECT_FALSE(db.GetQuotaConfigValue(kTempQuotaKey, &value));
- EXPECT_FALSE(db.GetQuotaConfigValue(kAvailSpaceKey, &value));
-
- EXPECT_TRUE(db.SetQuotaConfigValue(kTempQuotaKey, kValue1));
- EXPECT_TRUE(db.GetQuotaConfigValue(kTempQuotaKey, &value));
- EXPECT_EQ(kValue1, value);
-
- EXPECT_TRUE(db.SetQuotaConfigValue(kTempQuotaKey, kValue2));
- EXPECT_TRUE(db.GetQuotaConfigValue(kTempQuotaKey, &value));
- EXPECT_EQ(kValue2, value);
-
- EXPECT_TRUE(db.SetQuotaConfigValue(kAvailSpaceKey, kValue1));
- EXPECT_TRUE(db.GetQuotaConfigValue(kAvailSpaceKey, &value));
- EXPECT_EQ(kValue1, value);
-
- EXPECT_TRUE(db.SetQuotaConfigValue(kAvailSpaceKey, kValue2));
- EXPECT_TRUE(db.GetQuotaConfigValue(kAvailSpaceKey, &value));
- EXPECT_EQ(kValue2, value);
+ const int kQuota1 = 9999;
+ const int kQuota2 = 86420;
+
+ int64 quota = -1;
+ EXPECT_FALSE(db.GetGlobalQuota(kStorageTypeTemporary, &quota));
+ EXPECT_FALSE(db.GetGlobalQuota(kStorageTypePersistent, &quota));
+
+ EXPECT_TRUE(db.SetGlobalQuota(kStorageTypeTemporary, kQuota1));
+ EXPECT_TRUE(db.GetGlobalQuota(kStorageTypeTemporary, &quota));
+ EXPECT_EQ(kQuota1, quota);
+
+ EXPECT_TRUE(db.SetGlobalQuota(kStorageTypeTemporary, kQuota1 + 1024));
+ EXPECT_TRUE(db.GetGlobalQuota(kStorageTypeTemporary, &quota));
+ EXPECT_EQ(kQuota1 + 1024, quota);
+
+ EXPECT_FALSE(db.GetGlobalQuota(kStorageTypePersistent, &quota));
+
+ EXPECT_TRUE(db.SetGlobalQuota(kStorageTypePersistent, kQuota2));
+ EXPECT_TRUE(db.GetGlobalQuota(kStorageTypePersistent, &quota));
+ EXPECT_EQ(kQuota2, quota);
}
void OriginLastAccessTimeLRU(const FilePath& kDbFile) {
diff --git a/webkit/quota/quota_manager.cc b/webkit/quota/quota_manager.cc
index ad71c02..4ade94f 100644
--- a/webkit/quota/quota_manager.cc
+++ b/webkit/quota/quota_manager.cc
@@ -36,12 +36,38 @@ namespace quota {
namespace {
+const char kEnableQuotaEviction[] = "enable-quota-eviction";
const int64 kMBytes = 1024 * 1024;
const int kMinutesInMilliSeconds = 60 * 1000;
-const int64 kIncognitoDefaultTemporaryQuota = 50 * kMBytes;
-const int64 kReportHistogramInterval = 60 * 60 * 1000; // 1 hour
-const double kTemporaryQuotaRatioToAvail = 0.5; // 50%
+// Returns the initial size of the temporary storage quota.
+// (This just gives a default initial size; once its initial size is determined
+// it won't automatically be adjusted.)
+int64 GetInitialTemporaryStorageQuotaSize(const FilePath& path,
+ bool is_incognito) {
+ int64 free_space = base::SysInfo::AmountOfFreeDiskSpace(path);
+ UMA_HISTOGRAM_MBYTES("Quota.FreeDiskSpaceForProfile", free_space);
+
+ // Returns 0 (disables the temporary storage) if the available space is
+ // less than the twice of the default quota size.
+ if (free_space < QuotaManager::kTemporaryStorageQuotaDefaultSize * 2)
+ return 0;
+
+ if (is_incognito)
+ return QuotaManager::kIncognitoDefaultTemporaryQuota;
+
+ // Returns the default quota size while it is more than 5% of the
+ // available space.
+ if (free_space < QuotaManager::kTemporaryStorageQuotaDefaultSize * 20)
+ return QuotaManager::kTemporaryStorageQuotaDefaultSize;
+
+ // Returns the 5% of the available space while it does not exceed the
+ // maximum quota size (1GB).
+ if (free_space < QuotaManager::kTemporaryStorageQuotaMaxSize * 20)
+ return free_space / 20;
+
+ return QuotaManager::kTemporaryStorageQuotaMaxSize;
+}
void CountOriginType(const std::set<GURL>& origins,
SpecialStoragePolicy* policy,
@@ -65,6 +91,12 @@ void CountOriginType(const std::set<GURL>& origins,
} // anonymous namespace
+// TODO(kinuko): We will need to have different sizes for different platforms
+// (e.g. larger for desktop etc) and may want to have them in preferences.
+const int64 QuotaManager::kTemporaryStorageQuotaDefaultSize = 50 * kMBytes;
+const int64 QuotaManager::kTemporaryStorageQuotaMaxSize = 1 * 1024 * kMBytes;
+const int64 QuotaManager::kIncognitoDefaultTemporaryQuota = 50 * kMBytes;
+
const int QuotaManager::kPerHostTemporaryPortion = 5; // 20%
const char QuotaManager::kDatabaseName[] = "QuotaManager";
@@ -74,114 +106,94 @@ const int QuotaManager::kThresholdOfErrorsToBeBlacklisted = 3;
const int QuotaManager::kEvictionIntervalInMilliSeconds =
30 * kMinutesInMilliSeconds;
-// Callback translators.
-void CallGetUsageAndQuotaCallback(
- QuotaManager::GetUsageAndQuotaCallback* callback,
- bool unlimited,
- QuotaStatusCode status,
- const QuotaAndUsage& quota_and_usage) {
- int64 usage =
- unlimited ? quota_and_usage.unlimited_usage : quota_and_usage.usage;
- int64 quota = unlimited ? kint64max : quota_and_usage.quota;
- callback->Run(status, usage, quota);
- delete callback;
-}
-
-void CallQuotaCallback(
- QuotaCallback* callback,
- StorageType type,
- QuotaStatusCode status,
- const QuotaAndUsage& quota_and_usage) {
- callback->Run(status, type, quota_and_usage.quota);
- delete callback;
-}
+const base::TimeDelta QuotaManager::kReportHistogramInterval =
+ base::TimeDelta::FromMilliseconds(60 * 60 * 1000); // 1 hour
// This class is for posting GetUsage/GetQuota tasks, gathering
// results and dispatching GetAndQuota callbacks.
// This class is self-destructed.
class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask {
public:
- typedef UsageAndQuotaDispatcherCallback Callback;
- typedef std::deque<Callback> CallbackList;
+ typedef std::deque<GetUsageAndQuotaCallback*> CallbackList;
static UsageAndQuotaDispatcherTask* Create(
- QuotaManager* manager,
- bool global,
- const HostAndType& host_and_type);
+ QuotaManager* manager, const std::string& host, StorageType type);
// Returns true if it is the first call for this task; which means
// the caller needs to call Start().
- bool AddCallback(const Callback& callback) {
- callbacks_.push_back(callback);
- return (callbacks_.size() == 1);
+ bool AddCallback(GetUsageAndQuotaCallback* callback, bool unlimited) {
+ if (unlimited)
+ unlimited_callbacks_.push_back(callback);
+ else
+ callbacks_.push_back(callback);
+ return (callbacks_.size() + unlimited_callbacks_.size() == 1);
}
- void DidGetGlobalUsage(StorageType type, int64 usage, int64 unlimited_usage) {
- DCHECK_EQ(this->type(), type);
+ void DidGetGlobalUsage(StorageType type, int64 usage,
+ int64 unlimited_usage) {
+ DCHECK_EQ(type_, type);
DCHECK_GE(usage, unlimited_usage);
- if (quota_status_ == kQuotaStatusUnknown)
- quota_status_ = kQuotaStatusOk;
global_usage_ = usage;
global_unlimited_usage_ = unlimited_usage;
CheckCompleted();
}
- void DidGetHostUsage(const std::string& host, StorageType type, int64 usage) {
- DCHECK_EQ(this->host(), host);
- DCHECK_EQ(this->type(), type);
+ void DidGetHostUsage(const std::string& host,
+ StorageType type,
+ int64 usage) {
+ DCHECK_EQ(host_, host);
+ DCHECK_EQ(type_, type);
host_usage_ = usage;
CheckCompleted();
}
- void DidGetHostQuota(QuotaStatusCode status,
- const std::string& host,
- StorageType type,
- int64 host_quota) {
- DCHECK_EQ(this->host(), host);
- DCHECK_EQ(this->type(), type);
- if (quota_status_ == kQuotaStatusUnknown || quota_status_ == kQuotaStatusOk)
- quota_status_ = status;
- host_quota_ = host_quota;
+ void DidGetGlobalQuota(QuotaStatusCode status,
+ StorageType type,
+ int64 quota) {
+ DCHECK_EQ(type_, type);
+ quota_status_ = status;
+ quota_ = quota;
CheckCompleted();
}
- void DidGetAvailableSpace(QuotaStatusCode status, int64 space) {
- DCHECK_GE(space, 0);
- if (quota_status_ == kQuotaStatusUnknown || quota_status_ == kQuotaStatusOk)
- quota_status_ = status;
- available_space_ = space;
+ void DidGetHostQuota(QuotaStatusCode status,
+ const std::string& host,
+ StorageType type,
+ int64 quota) {
+ DCHECK_EQ(host_, host);
+ DCHECK_EQ(type_, type);
+ quota_status_ = status;
+ quota_ = quota;
CheckCompleted();
}
- bool IsStartable() const {
- return !started_ && !callbacks_.empty();
- }
-
protected:
UsageAndQuotaDispatcherTask(
QuotaManager* manager,
- const HostAndType& host_and_type)
+ const std::string& host,
+ StorageType type)
: QuotaTask(manager),
- host_and_type_(host_and_type),
- started_(false),
- host_quota_(-1),
+ host_(host),
+ type_(type),
+ quota_(-1),
global_usage_(-1),
global_unlimited_usage_(-1),
host_usage_(-1),
- available_space_(-1),
quota_status_(kQuotaStatusUnknown),
waiting_callbacks_(1),
callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
- virtual ~UsageAndQuotaDispatcherTask() {}
+ virtual ~UsageAndQuotaDispatcherTask() {
+ STLDeleteContainerPointers(callbacks_.begin(), callbacks_.end());
+ STLDeleteContainerPointers(unlimited_callbacks_.begin(),
+ unlimited_callbacks_.end());
+ }
// Subclasses must implement them.
virtual void RunBody() = 0;
virtual void DispatchCallbacks() = 0;
virtual void Run() OVERRIDE {
- DCHECK(!started_);
- started_ = true;
RunBody();
// We initialize waiting_callbacks to 1 so that we won't run
// the completion callback until here even some of the callbacks
@@ -190,7 +202,8 @@ class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask {
}
virtual void Aborted() OVERRIDE {
- CallCallbacksAndClear(kQuotaErrorAbort, 0, 0, 0, 0);
+ CallCallbacksAndClear(&callbacks_, kQuotaErrorAbort, 0, 0);
+ CallCallbacksAndClear(&unlimited_callbacks_, kQuotaErrorAbort, 0, 0);
DeleteSoon();
}
@@ -199,50 +212,29 @@ class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask {
}
void CallCallbacksAndClear(
- QuotaStatusCode status,
- int64 usage, int64 unlimited_usage, int64 quota,
- int64 available_space) {
- QuotaAndUsage qau = { usage, unlimited_usage, quota, available_space };
- for (CallbackList::iterator iter = callbacks_.begin();
- iter != callbacks_.end(); ++iter) {
- (*iter).Run(status, qau);
+ CallbackList* callbacks, QuotaStatusCode status,
+ int64 usage, int64 quota) {
+ for (CallbackList::iterator iter = callbacks->begin();
+ iter != callbacks->end(); ++iter) {
+ (*iter)->Run(status, usage, quota);
+ delete *iter;
}
- callbacks_.clear();
+ callbacks->clear();
}
QuotaManager* manager() const {
return static_cast<QuotaManager*>(observer());
}
- std::string host() const { return host_and_type_.first; }
- virtual StorageType type() const { return host_and_type_.second; }
- int64 host_quota() const { return host_quota_; }
+ std::string host() const { return host_; }
+ StorageType type() const { return type_; }
+ int64 quota() const { return quota_; }
int64 global_usage() const { return global_usage_; }
int64 global_unlimited_usage() const { return global_unlimited_usage_; }
int64 host_usage() const { return host_usage_; }
- int64 available_space() const { return available_space_; }
QuotaStatusCode quota_status() const { return quota_status_; }
CallbackList& callbacks() { return callbacks_; }
-
- // The main logic that determines the temporary global quota.
- int64 temporary_global_quota() const {
- DCHECK_EQ(type(), kStorageTypeTemporary);
- DCHECK(manager());
- DCHECK_GE(global_usage(), global_unlimited_usage());
- if (manager()->temporary_quota_override_ > 0) {
- // If the user has specified an explicit temporary quota, use the value.
- return manager()->temporary_quota_override_;
- }
- int64 limited_usage = global_usage() - global_unlimited_usage();
- int64 avail_space = available_space();
- if (avail_space < kint64max - limited_usage) {
- // We basically calculate the temporary quota by
- // [available_space + space_used_for_temp] * kTempQuotaRatio,
- // but make sure we'll have no overflow.
- avail_space += limited_usage;
- }
- return avail_space * kTemporaryQuotaRatioToAvail;
- }
+ CallbackList& unlimited_callbacks() { return unlimited_callbacks_; }
// Subclasses must call following methods to create a new 'waitable'
// callback, which decrements waiting_callbacks when it is called.
@@ -256,15 +248,15 @@ class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask {
return callback_factory_.NewCallback(
&UsageAndQuotaDispatcherTask::DidGetHostUsage);
}
- HostQuotaCallback* NewWaitableHostQuotaCallback() {
+ QuotaCallback* NewWaitableGlobalQuotaCallback() {
++waiting_callbacks_;
return callback_factory_.NewCallback(
- &UsageAndQuotaDispatcherTask::DidGetHostQuota);
+ &UsageAndQuotaDispatcherTask::DidGetGlobalQuota);
}
- AvailableSpaceCallback* NewWaitableAvailableSpaceCallback() {
+ HostQuotaCallback* NewWaitableHostQuotaCallback() {
++waiting_callbacks_;
return callback_factory_.NewCallback(
- &UsageAndQuotaDispatcherTask::DidGetAvailableSpace);
+ &UsageAndQuotaDispatcherTask::DidGetHostQuota);
}
private:
@@ -272,25 +264,26 @@ class QuotaManager::UsageAndQuotaDispatcherTask : public QuotaTask {
if (--waiting_callbacks_ <= 0) {
DispatchCallbacks();
DCHECK(callbacks_.empty());
+ DCHECK(unlimited_callbacks_.empty());
UsageAndQuotaDispatcherTaskMap& dispatcher_map =
manager()->usage_and_quota_dispatchers_;
- DCHECK(dispatcher_map.find(host_and_type_) != dispatcher_map.end());
- dispatcher_map.erase(host_and_type_);
+ DCHECK(dispatcher_map.find(std::make_pair(host_, type_)) !=
+ dispatcher_map.end());
+ dispatcher_map.erase(std::make_pair(host_, type_));
CallCompleted();
}
}
const std::string host_;
- const HostAndType host_and_type_;
- bool started_;
- int64 host_quota_;
+ const StorageType type_;
+ int64 quota_;
int64 global_usage_;
int64 global_unlimited_usage_;
int64 host_usage_;
- int64 available_space_;
QuotaStatusCode quota_status_;
CallbackList callbacks_;
+ CallbackList unlimited_callbacks_;
int waiting_callbacks_;
ScopedCallbackFactory<UsageAndQuotaDispatcherTask> callback_factory_;
@@ -362,8 +355,8 @@ class QuotaManager::UsageAndQuotaDispatcherTaskForTemporary
: public QuotaManager::UsageAndQuotaDispatcherTask {
public:
UsageAndQuotaDispatcherTaskForTemporary(
- QuotaManager* manager, const HostAndType& host_and_type)
- : UsageAndQuotaDispatcherTask(manager, host_and_type) {}
+ QuotaManager* manager, const std::string& host)
+ : UsageAndQuotaDispatcherTask(manager, host, kStorageTypeTemporary) {}
protected:
virtual void RunBody() OVERRIDE {
@@ -371,24 +364,34 @@ class QuotaManager::UsageAndQuotaDispatcherTaskForTemporary
NewWaitableGlobalUsageCallback());
manager()->temporary_usage_tracker_->GetHostUsage(
host(), NewWaitableHostUsageCallback());
- manager()->GetAvailableSpace(NewWaitableAvailableSpaceCallback());
+ manager()->GetTemporaryGlobalQuota(NewWaitableGlobalQuotaCallback());
}
virtual void DispatchCallbacks() OVERRIDE {
- // Allow an individual host to utilize a fraction of the total
- // pool available for temp storage.
- int64 host_quota = temporary_global_quota() / kPerHostTemporaryPortion;
-
- // But if total temp usage is over-budget, stop letting new data in
- // until we reclaim space.
- DCHECK_GE(global_usage(), global_unlimited_usage());
- int64 limited_global_usage = global_usage() - global_unlimited_usage();
- if (limited_global_usage > temporary_global_quota())
- host_quota = std::min(host_quota, host_usage());
-
- CallCallbacksAndClear(quota_status(),
- host_usage(), host_usage(), host_quota,
- available_space());
+ // Due to a mismatch of models between same-origin (required by stds) vs
+ // per-host (as this info is viewed in the UI) vs the extension systems
+ // notion of webextents (the basis of granting unlimited rights),
+ // we can end up with both 'unlimited' and 'limited' callbacks to invoke.
+ // Should be rare, but it can happen.
+
+ CallCallbacksAndClear(&unlimited_callbacks(), quota_status(),
+ host_usage(), kint64max);
+
+ if (!callbacks().empty()) {
+ // Allow an individual host to utilize a fraction of the total
+ // pool available for temp storage.
+ int64 host_quota = quota() / kPerHostTemporaryPortion;
+
+ // But if total temp usage is over-budget, stop letting new data in
+ // until we reclaim space.
+ DCHECK_GE(global_usage(), global_unlimited_usage());
+ int64 limited_global_usage = global_usage() - global_unlimited_usage();
+ if (limited_global_usage > quota())
+ host_quota = std::min(host_quota, host_usage());
+
+ CallCallbacksAndClear(&callbacks(), quota_status(),
+ host_usage(), host_quota);
+ }
}
};
@@ -396,8 +399,8 @@ class QuotaManager::UsageAndQuotaDispatcherTaskForPersistent
: public QuotaManager::UsageAndQuotaDispatcherTask {
public:
UsageAndQuotaDispatcherTaskForPersistent(
- QuotaManager* manager, const HostAndType& host_and_type)
- : UsageAndQuotaDispatcherTask(manager, host_and_type) {}
+ QuotaManager* manager, const std::string& host)
+ : UsageAndQuotaDispatcherTask(manager, host, kStorageTypePersistent) {}
protected:
virtual void RunBody() OVERRIDE {
@@ -408,51 +411,24 @@ class QuotaManager::UsageAndQuotaDispatcherTaskForPersistent
}
virtual void DispatchCallbacks() OVERRIDE {
- CallCallbacksAndClear(quota_status(),
- host_usage(), host_usage(), host_quota(),
- available_space());
+ CallCallbacksAndClear(&callbacks(), quota_status(),
+ host_usage(), quota());
+ CallCallbacksAndClear(&unlimited_callbacks(), quota_status(),
+ host_usage(), kint64max);
}
};
-class QuotaManager::UsageAndQuotaDispatcherTaskForTemporaryGlobal
- : public QuotaManager::UsageAndQuotaDispatcherTask {
- public:
- UsageAndQuotaDispatcherTaskForTemporaryGlobal(
- QuotaManager* manager, const HostAndType& host_and_type)
- : UsageAndQuotaDispatcherTask(manager, host_and_type) {}
-
- protected:
- virtual void RunBody() OVERRIDE {
- manager()->temporary_usage_tracker_->GetGlobalUsage(
- NewWaitableGlobalUsageCallback());
- manager()->GetAvailableSpace(NewWaitableAvailableSpaceCallback());
- }
-
- virtual void DispatchCallbacks() OVERRIDE {
- CallCallbacksAndClear(quota_status(),
- global_usage(), global_unlimited_usage(),
- temporary_global_quota(),
- available_space());
- }
-
- virtual StorageType type() const { return kStorageTypeTemporary; }
-};
-
// static
QuotaManager::UsageAndQuotaDispatcherTask*
QuotaManager::UsageAndQuotaDispatcherTask::Create(
- QuotaManager* manager, bool global,
- const QuotaManager::HostAndType& host_and_type) {
- if (global)
- return new UsageAndQuotaDispatcherTaskForTemporaryGlobal(
- manager, host_and_type);
- switch (host_and_type.second) {
+ QuotaManager* manager, const std::string& host, StorageType type) {
+ switch (type) {
case kStorageTypeTemporary:
return new UsageAndQuotaDispatcherTaskForTemporary(
- manager, host_and_type);
+ manager, host);
case kStorageTypePersistent:
return new UsageAndQuotaDispatcherTaskForPersistent(
- manager, host_and_type);
+ manager, host);
default:
NOTREACHED();
}
@@ -558,72 +534,83 @@ class QuotaManager::DatabaseTaskBase : public QuotaThreadTask {
class QuotaManager::InitializeTask : public QuotaManager::DatabaseTaskBase {
public:
- InitializeTask(QuotaManager* manager)
+ InitializeTask(
+ QuotaManager* manager,
+ const FilePath& profile_path,
+ bool is_incognito)
: DatabaseTaskBase(manager),
- temporary_quota_override_(-1),
- desired_available_space_(-1) {
- DCHECK(manager);
+ profile_path_(profile_path),
+ is_incognito_(is_incognito),
+ need_initialize_origins_(false),
+ temporary_storage_quota_(-1) {
}
protected:
virtual void RunOnTargetThread() OVERRIDE {
- // See if we have overriding temporary quota configuration.
- database()->GetQuotaConfigValue(QuotaDatabase::kTemporaryQuotaOverrideKey,
- &temporary_quota_override_);
- database()->GetQuotaConfigValue(QuotaDatabase::kDesiredAvailableSpaceKey,
- &desired_available_space_);
+ // Initializes the global temporary quota.
+ if (!database()->GetGlobalQuota(
+ kStorageTypeTemporary, &temporary_storage_quota_)) {
+ // If the temporary storage quota size has not been initialized,
+ // make up one and store it in the database.
+ temporary_storage_quota_ = GetInitialTemporaryStorageQuotaSize(
+ profile_path_, is_incognito_);
+ UMA_HISTOGRAM_MBYTES("Quota.InitialTemporaryGlobalStorageQuota",
+ temporary_storage_quota_);
+ if (!database()->SetGlobalQuota(
+ kStorageTypeTemporary, temporary_storage_quota_)) {
+ set_db_disabled(true);
+ }
+ }
+ if (!db_disabled())
+ need_initialize_origins_ = !database()->IsOriginDatabaseBootstrapped();
}
virtual void DatabaseTaskCompleted() OVERRIDE {
- manager()->temporary_quota_override_ = temporary_quota_override_;
- manager()->desired_available_space_ = desired_available_space_;
- manager()->temporary_quota_initialized_ = true;
- manager()->DidRunInitializeTask();
+ manager()->need_initialize_origins_ = need_initialize_origins_;
+ manager()->DidInitializeTemporaryGlobalQuota(temporary_storage_quota_);
+ manager()->histogram_timer_.Start(FROM_HERE,
+ QuotaManager::kReportHistogramInterval,
+ manager(),
+ &QuotaManager::ReportHistogram);
}
private:
- int64 temporary_quota_override_;
- int64 desired_available_space_;
+ FilePath profile_path_;
+ bool is_incognito_;
+ bool need_initialize_origins_;
+ int64 temporary_storage_quota_;
};
-class QuotaManager::UpdateTemporaryQuotaOverrideTask
+class QuotaManager::UpdateTemporaryGlobalQuotaTask
: public QuotaManager::DatabaseTaskBase {
public:
- UpdateTemporaryQuotaOverrideTask(
+ UpdateTemporaryGlobalQuotaTask(
QuotaManager* manager,
int64 new_quota,
QuotaCallback* callback)
: DatabaseTaskBase(manager),
new_quota_(new_quota),
- callback_(callback) {}
+ callback_(callback) {
+ DCHECK_GE(new_quota, 0);
+ }
protected:
virtual void RunOnTargetThread() OVERRIDE {
- if (!database()->SetQuotaConfigValue(
- QuotaDatabase::kTemporaryQuotaOverrideKey, new_quota_)) {
+ if (!database()->SetGlobalQuota(kStorageTypeTemporary, new_quota_)) {
set_db_disabled(true);
- new_quota_ = -1;
- return;
+ new_quota_ = 0;
}
}
virtual void DatabaseTaskCompleted() OVERRIDE {
+ callback_->Run(db_disabled() ? kQuotaErrorInvalidAccess : kQuotaStatusOk,
+ kStorageTypeTemporary, new_quota_);
if (!db_disabled()) {
- manager()->temporary_quota_override_ = new_quota_;
- CallCallback(kQuotaStatusOk, kStorageTypeTemporary, new_quota_);
- } else {
- CallCallback(kQuotaErrorInvalidAccess, kStorageTypeTemporary, new_quota_);
+ manager()->temporary_global_quota_ = new_quota_;
}
}
private:
- void CallCallback(QuotaStatusCode status, StorageType type, int64 quota) {
- if (callback_.get()) {
- callback_->Run(status, type, quota);
- callback_.reset();
- }
- }
-
int64 new_quota_;
scoped_ptr<QuotaCallback> callback_;
};
@@ -721,8 +708,9 @@ class QuotaManager::GetLRUOriginTask
protected:
virtual void RunOnTargetThread() OVERRIDE {
- database()->GetLRUOrigin(
- type_, exceptions_, special_storage_policy_, &url_);
+ if (!database()->GetLRUOrigin(type_, exceptions_,
+ special_storage_policy_, &url_))
+ set_db_disabled(true);
}
virtual void DatabaseTaskCompleted() OVERRIDE {
@@ -804,12 +792,13 @@ class QuotaManager::AvailableSpaceQueryTask : public QuotaThreadTask {
public:
AvailableSpaceQueryTask(
QuotaManager* manager,
+ scoped_refptr<base::MessageLoopProxy> db_message_loop,
+ const FilePath& profile_path,
AvailableSpaceCallback* callback)
- : QuotaThreadTask(manager, manager->db_thread_),
- profile_path_(manager->profile_path_),
+ : QuotaThreadTask(manager, db_message_loop),
+ profile_path_(profile_path),
space_(-1),
- callback_(callback) {
- }
+ callback_(callback) {}
virtual ~AvailableSpaceQueryTask() {}
protected:
@@ -818,7 +807,7 @@ class QuotaManager::AvailableSpaceQueryTask : public QuotaThreadTask {
}
virtual void Aborted() OVERRIDE {
- callback_.reset();
+ callback_->Run(kQuotaErrorAbort, -1);
}
virtual void Completed() OVERRIDE {
@@ -1021,9 +1010,8 @@ QuotaManager::QuotaManager(bool is_incognito,
eviction_disabled_(false),
io_thread_(io_thread),
db_thread_(db_thread),
- temporary_quota_initialized_(false),
- temporary_quota_override_(-1),
- desired_available_space_(-1),
+ need_initialize_origins_(false),
+ temporary_global_quota_(-1),
special_storage_policy_(special_storage_policy),
callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}
@@ -1045,54 +1033,71 @@ void QuotaManager::GetUsageInfo(GetUsageInfoCallback* callback) {
void QuotaManager::GetUsageAndQuota(
const GURL& origin, StorageType type,
- GetUsageAndQuotaCallback* callback) {
- GetUsageAndQuotaInternal(origin, type, false /* global */,
- base::Bind(&CallGetUsageAndQuotaCallback,
- callback, IsStorageUnlimited(origin)));
-}
+ GetUsageAndQuotaCallback* callback_ptr) {
+ scoped_ptr<GetUsageAndQuotaCallback> callback(callback_ptr);
+ LazyInitialize();
-void QuotaManager::GetAvailableSpace(AvailableSpaceCallback* callback) {
- if (is_incognito_) {
- callback->Run(kQuotaStatusOk, kIncognitoDefaultTemporaryQuota);
- delete callback;
+ if (type == kStorageTypeUnknown) {
+ // Quota only supports temporary/persistent types.
+ callback->Run(kQuotaErrorNotSupported, 0, 0);
return;
}
- make_scoped_refptr(new AvailableSpaceQueryTask(this, callback))->Start();
+
+ // note: returns host usage and quota
+ std::string host = net::GetHostOrSpecFromURL(origin);
+ UsageAndQuotaDispatcherTaskMap::iterator found =
+ usage_and_quota_dispatchers_.find(std::make_pair(host, type));
+ if (found == usage_and_quota_dispatchers_.end()) {
+ UsageAndQuotaDispatcherTask* dispatcher =
+ UsageAndQuotaDispatcherTask::Create(this, host, type);
+ found = usage_and_quota_dispatchers_.insert(
+ std::make_pair(std::make_pair(host, type), dispatcher)).first;
+ }
+ if (found->second->AddCallback(
+ callback.release(), IsStorageUnlimited(origin))) {
+ found->second->Start();
+ }
+}
+
+void QuotaManager::GetAvailableSpace(AvailableSpaceCallback* callback) {
+ scoped_refptr<AvailableSpaceQueryTask> task(
+ new AvailableSpaceQueryTask(this, db_thread_, profile_path_, callback));
+ task->Start();
}
void QuotaManager::GetTemporaryGlobalQuota(QuotaCallback* callback) {
- if (temporary_quota_override_ > 0) {
- callback->Run(kQuotaStatusOk, kStorageTypeTemporary,
- temporary_quota_override_);
+ LazyInitialize();
+ if (temporary_global_quota_ >= 0) {
+ // TODO(kinuko): We may want to adjust the quota when the current
+ // available space in the hard drive is getting tight.
+ callback->Run(kQuotaStatusOk,
+ kStorageTypeTemporary, temporary_global_quota_);
delete callback;
return;
}
- GetUsageAndQuotaInternal(
- GURL(), kStorageTypeTemporary, true /* global */,
- base::Bind(&CallQuotaCallback, callback, kStorageTypeTemporary));
+ // They are called upon completion of InitializeTask.
+ temporary_global_quota_callbacks_.Add(callback);
}
-void QuotaManager::SetTemporaryGlobalOverrideQuota(
- int64 new_quota, QuotaCallback* callback_ptr) {
- scoped_ptr<QuotaCallback> callback(callback_ptr);
+void QuotaManager::SetTemporaryGlobalQuota(int64 new_quota,
+ QuotaCallback* callback) {
LazyInitialize();
-
if (new_quota < 0) {
- if (callback.get())
- callback->Run(kQuotaErrorInvalidModification,
- kStorageTypeTemporary, -1);
+ callback->Run(kQuotaErrorInvalidModification,
+ kStorageTypeTemporary, -1);
+ delete callback;
return;
}
- if (db_disabled_) {
- if (callback.get())
- callback->Run(kQuotaErrorInvalidAccess,
- kStorageTypeTemporary, -1);
- return;
+ if (!db_disabled_) {
+ scoped_refptr<UpdateTemporaryGlobalQuotaTask> task(
+ new UpdateTemporaryGlobalQuotaTask(this, new_quota, callback));
+ task->Start();
+ } else {
+ callback->Run(kQuotaErrorInvalidAccess,
+ kStorageTypeTemporary, -1);
+ delete callback;
}
-
- make_scoped_refptr(new UpdateTemporaryQuotaOverrideTask(
- this, new_quota, callback.release()))->Start();
}
void QuotaManager::GetPersistentHostQuota(const std::string& host,
@@ -1191,7 +1196,9 @@ void QuotaManager::LazyInitialize() {
new UsageTracker(clients_, kStorageTypePersistent,
special_storage_policy_));
- make_scoped_refptr(new InitializeTask(this))->Start();
+ scoped_refptr<InitializeTask> task(
+ new InitializeTask(this, profile_path_, is_incognito_));
+ task->Start();
}
void QuotaManager::RegisterClient(QuotaClient* client) {
@@ -1322,46 +1329,6 @@ void QuotaManager::NotifyStorageModifiedInternal(
this, origin, type, modified_time))->Start();
}
-void QuotaManager::GetUsageAndQuotaInternal(
- const GURL& origin, StorageType type, bool global,
- const UsageAndQuotaDispatcherCallback& callback) {
- LazyInitialize();
-
- StorageType requested_type = type;
- if (type == kStorageTypeUnknown) {
- // Quota only supports temporary/persistent types.
- callback.Run(kQuotaErrorNotSupported, QuotaAndUsage());
- return;
- }
-
- // Special internal type for querying global usage and quota.
- const int kStorageTypeTemporaryGlobal = kStorageTypeTemporary + 100;
- if (global) {
- DCHECK_EQ(kStorageTypeTemporary, type);
- type = static_cast<StorageType>(kStorageTypeTemporaryGlobal);
- }
-
- std::string host = net::GetHostOrSpecFromURL(origin);
- HostAndType host_and_type = std::make_pair(host, type);
- UsageAndQuotaDispatcherTaskMap::iterator found =
- usage_and_quota_dispatchers_.find(host_and_type);
- if (found == usage_and_quota_dispatchers_.end()) {
- UsageAndQuotaDispatcherTask* dispatcher =
- UsageAndQuotaDispatcherTask::Create(this, global, host_and_type);
- found = usage_and_quota_dispatchers_.insert(
- std::make_pair(host_and_type, dispatcher)).first;
- }
- // Start the dispatcher if it is the first one and temporary_quota_override
- // is already initialized iff the requested type is temporary.
- // (The first dispatcher task for temporary will be kicked in
- // DidRunInitializeTask if temporary_quota_initialized_ is false here.)
- if (found->second->AddCallback(callback) &&
- (requested_type != kStorageTypeTemporary ||
- temporary_quota_initialized_)) {
- found->second->Start();
- }
-}
-
void QuotaManager::DumpQuotaTable(DumpQuotaTableCallback* callback) {
make_scoped_refptr(new DumpQuotaTableTask(this, callback))->Start();
}
@@ -1431,20 +1398,58 @@ void QuotaManager::EvictOriginData(
&QuotaManager::DidOriginDataEvicted));
}
+void QuotaManager::DidGetAvailableSpaceForEviction(
+ QuotaStatusCode status,
+ int64 available_space) {
+ eviction_context_.get_usage_and_quota_callback->Run(status,
+ eviction_context_.usage,
+ eviction_context_.unlimited_usage,
+ eviction_context_.quota, available_space);
+ eviction_context_.get_usage_and_quota_callback.reset();
+}
+
+void QuotaManager::DidGetGlobalQuotaForEviction(
+ QuotaStatusCode status,
+ StorageType type,
+ int64 quota) {
+ DCHECK_EQ(type, kStorageTypeTemporary);
+ if (status != kQuotaStatusOk) {
+ eviction_context_.get_usage_and_quota_callback->Run(
+ status, 0, 0, 0, 0);
+ eviction_context_.get_usage_and_quota_callback.reset();
+ return;
+ }
+
+ eviction_context_.quota = quota;
+ GetAvailableSpace(callback_factory_.
+ NewCallback(&QuotaManager::DidGetAvailableSpaceForEviction));
+}
+
+void QuotaManager::DidGetGlobalUsageForEviction(
+ StorageType type, int64 usage, int64 unlimited_usage) {
+ DCHECK_EQ(type, kStorageTypeTemporary);
+ DCHECK_GE(usage, unlimited_usage);
+ eviction_context_.usage = usage;
+ eviction_context_.unlimited_usage = unlimited_usage;
+ GetTemporaryGlobalQuota(callback_factory_.
+ NewCallback(&QuotaManager::DidGetGlobalQuotaForEviction));
+}
+
void QuotaManager::GetUsageAndQuotaForEviction(
- const GetUsageAndQuotaForEvictionCallback& callback) {
+ GetUsageAndQuotaForEvictionCallback* callback) {
DCHECK(io_thread_->BelongsToCurrentThread());
- GetUsageAndQuotaInternal(
- GURL(), kStorageTypeTemporary, true /* global */, callback);
+ DCHECK(!eviction_context_.get_usage_and_quota_callback.get());
+
+ eviction_context_.get_usage_and_quota_callback.reset(callback);
+ // TODO(dmikurube): Make kStorageTypeTemporary an argument.
+ GetGlobalUsage(kStorageTypeTemporary, callback_factory_.
+ NewCallback(&QuotaManager::DidGetGlobalUsageForEviction));
}
void QuotaManager::StartEviction() {
DCHECK(!temporary_storage_evictor_.get());
- temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor(
- this, kEvictionIntervalInMilliSeconds));
- if (desired_available_space_ >= 0)
- temporary_storage_evictor_->set_min_available_disk_space_to_start_eviction(
- desired_available_space_);
+ temporary_storage_evictor_.reset(new QuotaTemporaryStorageEvictor(this,
+ kEvictionIntervalInMilliSeconds));
temporary_storage_evictor_->Start();
}
@@ -1503,40 +1508,38 @@ void QuotaManager::DidGetPersistentGlobalUsageForHistogram(
unlimited_origins);
}
-void QuotaManager::DidRunInitializeTask() {
- histogram_timer_.Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(
- kReportHistogramInterval),
- this, &QuotaManager::ReportHistogram);
+void QuotaManager::DidInitializeTemporaryGlobalQuota(int64 quota) {
+ temporary_global_quota_ = quota;
+ temporary_global_quota_callbacks_.Run(
+ db_disabled_ ? kQuotaErrorInvalidAccess : kQuotaStatusOk,
+ kStorageTypeTemporary, quota);
- DCHECK(temporary_quota_initialized_);
+ if (db_disabled_ || eviction_disabled_)
+ return;
- // Kick the tasks that have been waiting for the
- // temporary_quota_initialized_ to be initialized (if there're any).
- for (UsageAndQuotaDispatcherTaskMap::iterator iter =
- usage_and_quota_dispatchers_.begin();
- iter != usage_and_quota_dispatchers_.end(); ++iter) {
- if (iter->second->IsStartable())
- iter->second->Start();
+ if (!need_initialize_origins_) {
+ StartEviction();
+ return;
}
- // Kick the first GetTemporaryGlobalQuota. This internally fetches (and
- // caches) the usage of all origins and checks the available disk space.
- GetTemporaryGlobalQuota(callback_factory_.NewCallback(
- &QuotaManager::DidGetInitialTemporaryGlobalQuota));
+ // We seem to need to initialize the origin table in the database.
+ // Kick the first GetGlobalUsage for temporary storage to cache a list
+ // of origins that have data in temporary storage to register them
+ // in the database. (We'll need the global temporary usage anyway
+ // for eviction later.)
+ temporary_usage_tracker_->GetGlobalUsage(callback_factory_.NewCallback(
+ &QuotaManager::DidRunInitialGetTemporaryGlobalUsage));
}
-void QuotaManager::DidGetInitialTemporaryGlobalQuota(
- QuotaStatusCode status, StorageType type, int64 quota_unused) {
+void QuotaManager::DidRunInitialGetTemporaryGlobalUsage(
+ StorageType type, int64 usage_unused, int64 unlimited_usage_unused) {
DCHECK_EQ(type, kStorageTypeTemporary);
-
- if (eviction_disabled_)
- return;
-
// This will call the StartEviction() when initial origin registration
// is completed.
- make_scoped_refptr(new InitializeTemporaryOriginsInfoTask(
- this, temporary_usage_tracker_.get()))->Start();
+ scoped_refptr<InitializeTemporaryOriginsInfoTask> task(
+ new InitializeTemporaryOriginsInfoTask(
+ this, temporary_usage_tracker_.get()));
+ task->Start();
}
void QuotaManager::DidGetDatabaseLRUOrigin(const GURL& origin) {
diff --git a/webkit/quota/quota_manager.h b/webkit/quota/quota_manager.h
index df701d6..2d0de6a 100644
--- a/webkit/quota/quota_manager.h
+++ b/webkit/quota/quota_manager.h
@@ -45,24 +45,20 @@ class QuotaTemporaryStorageEvictor;
class UsageTracker;
class MockQuotaManager;
-struct QuotaAndUsage {
- int64 usage;
- int64 unlimited_usage;
- int64 quota;
- int64 available_disk_space;
-};
-
// An interface called by QuotaTemporaryStorageEvictor.
class QuotaEvictionHandler {
public:
+ virtual ~QuotaEvictionHandler() {}
+
typedef Callback1<const GURL&>::Type GetLRUOriginCallback;
typedef StatusCallback EvictOriginDataCallback;
- typedef base::Callback<void(QuotaStatusCode,
- const QuotaAndUsage& quota_and_usage)>
+ typedef Callback5<QuotaStatusCode,
+ int64 /* usage */,
+ int64 /* unlimited_usage */,
+ int64 /* quota */,
+ int64 /* physical_available */ >::Type
GetUsageAndQuotaForEvictionCallback;
- virtual ~QuotaEvictionHandler() {}
-
// Returns the least recently used origin. It might return empty
// GURL when there are no evictable origins.
virtual void GetLRUOrigin(
@@ -75,7 +71,7 @@ class QuotaEvictionHandler {
EvictOriginDataCallback* callback) = 0;
virtual void GetUsageAndQuotaForEviction(
- const GetUsageAndQuotaForEvictionCallback& callback) = 0;
+ GetUsageAndQuotaForEvictionCallback* callback) = 0;
};
struct UsageInfo {
@@ -153,11 +149,7 @@ class QuotaManager : public QuotaTaskObserver,
// Called by UI and internal modules.
void GetAvailableSpace(AvailableSpaceCallback* callback);
void GetTemporaryGlobalQuota(QuotaCallback* callback);
-
- // Ok to call with NULL callback.
- void SetTemporaryGlobalOverrideQuota(int64 new_quota,
- QuotaCallback* callback);
-
+ void SetTemporaryGlobalQuota(int64 new_quota, QuotaCallback* callback);
void GetPersistentHostQuota(const std::string& host,
HostQuotaCallback* callback);
void SetPersistentHostQuota(const std::string& host,
@@ -180,6 +172,11 @@ class QuotaManager : public QuotaTaskObserver,
bool ResetUsageTracker(StorageType type);
+ // Used to determine the total size of the temp pool.
+ static const int64 kTemporaryStorageQuotaDefaultSize;
+ static const int64 kTemporaryStorageQuotaMaxSize;
+ static const int64 kIncognitoDefaultTemporaryQuota;
+
// Determines the portion of the temp pool that can be
// utilized by a single host (ie. 5 for 20%).
static const int kPerHostTemporaryPortion;
@@ -189,11 +186,12 @@ class QuotaManager : public QuotaTaskObserver,
static const int kThresholdOfErrorsToBeBlacklisted;
static const int kEvictionIntervalInMilliSeconds;
+ static const base::TimeDelta kReportHistogramInterval;
private:
class DatabaseTaskBase;
class InitializeTask;
- class UpdateTemporaryQuotaOverrideTask;
+ class UpdateTemporaryGlobalQuotaTask;
class GetPersistentHostQuotaTask;
class UpdatePersistentHostQuotaTask;
class GetLRUOriginTask;
@@ -207,7 +205,6 @@ class QuotaManager : public QuotaTaskObserver,
class UsageAndQuotaDispatcherTask;
class UsageAndQuotaDispatcherTaskForTemporary;
class UsageAndQuotaDispatcherTaskForPersistent;
- class UsageAndQuotaDispatcherTaskForTemporaryGlobal;
class OriginDataDeleter;
@@ -225,20 +222,29 @@ class QuotaManager : public QuotaTaskObserver,
DumpOriginInfoTableCallback;
struct EvictionContext {
- EvictionContext() : evicted_type(kStorageTypeUnknown) {}
+ EvictionContext()
+ : evicted_type(kStorageTypeUnknown),
+ usage(0),
+ unlimited_usage(0),
+ quota(0) {}
virtual ~EvictionContext() {}
+
GURL evicted_origin;
StorageType evicted_type;
+
scoped_ptr<EvictOriginDataCallback> evict_origin_data_callback;
+
+ scoped_ptr<GetUsageAndQuotaForEvictionCallback>
+ get_usage_and_quota_callback;
+ int64 usage;
+ int64 unlimited_usage;
+ int64 quota;
};
typedef std::pair<std::string, StorageType> HostAndType;
typedef std::map<HostAndType, UsageAndQuotaDispatcherTask*>
UsageAndQuotaDispatcherTaskMap;
- typedef QuotaEvictionHandler::GetUsageAndQuotaForEvictionCallback
- UsageAndQuotaDispatcherCallback;
-
friend class quota_internals::QuotaInternalsProxy;
friend struct QuotaManagerDeleter;
friend class MockStorageClient;
@@ -277,13 +283,6 @@ class QuotaManager : public QuotaTaskObserver,
int64 delta,
base::Time modified_time);
- // |origin| can be empty if |global| is true.
- void GetUsageAndQuotaInternal(
- const GURL& origin,
- StorageType type,
- bool global,
- const UsageAndQuotaDispatcherCallback& callback);
-
void DumpQuotaTable(DumpQuotaTableCallback* callback);
void DumpOriginInfoTable(DumpOriginInfoTableCallback* callback);
@@ -292,12 +291,16 @@ class QuotaManager : public QuotaTaskObserver,
void DeleteOriginFromDatabase(const GURL& origin, StorageType type);
void DidOriginDataEvicted(QuotaStatusCode status);
- void DidGetGlobalUsageAndQuotaForEviction(QuotaStatusCode status,
- StorageType type,
- int64 usage,
- int64 unlimited_usage,
- int64 quota,
- int64 available_space);
+ void DidGetAvailableSpaceForEviction(
+ QuotaStatusCode status,
+ int64 available_space);
+ void DidGetGlobalQuotaForEviction(
+ QuotaStatusCode status,
+ StorageType type,
+ int64 quota);
+ void DidGetGlobalUsageForEviction(StorageType type,
+ int64 usage,
+ int64 unlimited_usage);
void ReportHistogram();
void DidGetTemporaryGlobalUsageForHistogram(StorageType type,
@@ -316,12 +319,11 @@ class QuotaManager : public QuotaTaskObserver,
StorageType type,
EvictOriginDataCallback* callback) OVERRIDE;
virtual void GetUsageAndQuotaForEviction(
- const GetUsageAndQuotaForEvictionCallback& callback) OVERRIDE;
+ GetUsageAndQuotaForEvictionCallback* callback) OVERRIDE;
- void DidRunInitializeTask();
- void DidGetInitialTemporaryGlobalQuota(QuotaStatusCode status,
- StorageType type,
- int64 quota_unused);
+ void DidInitializeTemporaryGlobalQuota(int64 quota);
+ void DidRunInitialGetTemporaryGlobalUsage(StorageType type, int64 usage,
+ int64 unlimited_usage);
void DidGetDatabaseLRUOrigin(const GURL& origin);
void DeleteOnCorrectThread() const;
@@ -336,6 +338,7 @@ class QuotaManager : public QuotaTaskObserver,
scoped_refptr<base::MessageLoopProxy> db_thread_;
mutable scoped_ptr<QuotaDatabase> database_;
+ bool need_initialize_origins_;
scoped_ptr<GetLRUOriginCallback> lru_origin_callback_;
std::set<GURL> access_notified_origins_;
@@ -351,10 +354,8 @@ class QuotaManager : public QuotaTaskObserver,
UsageAndQuotaDispatcherTaskMap usage_and_quota_dispatchers_;
- bool temporary_quota_initialized_;
- int64 temporary_quota_override_;
-
- int64 desired_available_space_;
+ int64 temporary_global_quota_;
+ QuotaCallbackQueue temporary_global_quota_callbacks_;
// Map from origin to count.
std::map<GURL, int> origins_in_use_;
diff --git a/webkit/quota/quota_manager_unittest.cc b/webkit/quota/quota_manager_unittest.cc
index 3a34e9f..e9f4ab3 100644
--- a/webkit/quota/quota_manager_unittest.cc
+++ b/webkit/quota/quota_manager_unittest.cc
@@ -6,11 +6,9 @@
#include <sstream>
#include <vector>
-#include "base/bind.h"
#include "base/file_util.h"
#include "base/memory/scoped_callback_factory.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/scoped_temp_dir.h"
@@ -19,12 +17,16 @@
#include "base/time.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageQuotaError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageQuotaType.h"
#include "webkit/quota/mock_special_storage_policy.h"
#include "webkit/quota/mock_storage_client.h"
#include "webkit/quota/quota_database.h"
#include "webkit/quota/quota_manager.h"
using base::MessageLoopProxy;
+using WebKit::WebStorageQuotaError;
+using WebKit::WebStorageQuotaType;
namespace quota {
@@ -41,7 +43,6 @@ class QuotaManagerTest : public testing::Test {
public:
QuotaManagerTest()
: callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
- weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
mock_time_counter_(0) {
}
@@ -102,8 +103,7 @@ class QuotaManagerTest : public testing::Test {
void SetTemporaryGlobalQuota(int64 new_quota) {
quota_status_ = kQuotaStatusUnknown;
quota_ = -1;
- quota_manager_->SetTemporaryGlobalOverrideQuota(
- new_quota,
+ quota_manager_->SetTemporaryGlobalQuota(new_quota,
callback_factory_.NewCallback(
&QuotaManagerTest::DidGetQuota));
}
@@ -193,8 +193,8 @@ class QuotaManagerTest : public testing::Test {
quota_ = -1;
available_space_ = -1;
quota_manager_->GetUsageAndQuotaForEviction(
- base::Bind(&QuotaManagerTest::DidGetUsageAndQuotaForEviction,
- weak_factory_.GetWeakPtr()));
+ callback_factory_.NewCallback(
+ &QuotaManagerTest::DidGetUsageAndQuotaForEviction));
}
void GetCachedOrigins(StorageType type, std::set<GURL>* origins) {
@@ -305,12 +305,12 @@ class QuotaManagerTest : public testing::Test {
}
void DidGetUsageAndQuotaForEviction(QuotaStatusCode status,
- const QuotaAndUsage& quota_and_usage) {
+ int64 usage, int64 unlimited_usage, int64 quota, int64 available_space) {
quota_status_ = status;
- usage_ = quota_and_usage.usage;
- unlimited_usage_ = quota_and_usage.unlimited_usage;
- quota_ = quota_and_usage.quota;
- available_space_ = quota_and_usage.available_disk_space;
+ usage_ = usage;
+ unlimited_usage_ = unlimited_usage;
+ quota_ = quota;
+ available_space_ = available_space;
}
void DidGetLRUOrigin(const GURL& origin) {
@@ -375,7 +375,6 @@ class QuotaManagerTest : public testing::Test {
ScopedTempDir data_dir_;
base::ScopedCallbackFactory<QuotaManagerTest> callback_factory_;
- base::WeakPtrFactory<QuotaManagerTest> weak_factory_;
scoped_refptr<QuotaManager> quota_manager_;
scoped_refptr<MockSpecialStoragePolicy> mock_special_storage_policy_;
@@ -441,7 +440,7 @@ TEST_F(QuotaManagerTest, GetUsageInfo) {
TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) {
static const MockOriginData kData[] = {
- { "http://foo.com/", kTemp, 10 },
+ { "http://foo.com/", kTemp, 10 },
{ "http://foo.com/", kPerm, 80 },
};
RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData)));
@@ -457,6 +456,7 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) {
EXPECT_EQ(kQuotaStatusOk, status());
EXPECT_EQ(10, usage());
EXPECT_LE(0, quota());
+ EXPECT_GE(QuotaManager::kTemporaryStorageQuotaMaxSize, quota());
int64 quota_returned_for_foo = quota();
GetUsageAndQuota(GURL("http://bar.com/"), kTemp);
@@ -534,7 +534,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) {
{ "http://bar.com/", kTemp, 5 },
{ "https://bar.com/", kTemp, 7 },
{ "http://baz.com/", kTemp, 30 },
- { "http://foo.com/", kPerm, 40 },
+ { "http://foo.com/", kPerm, 40 },
};
RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData)));
@@ -655,9 +655,9 @@ TEST_F(QuotaManagerTest, GetTemporaryUsage_WithModify) {
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/", kTemp, 10 },
+ { "http://foo.com:8080/", kTemp, 20 },
+ { "http://bar.com/", kTemp, 13 },
{ "http://foo.com/", kPerm, 40 },
};
RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData)));
@@ -689,9 +689,9 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) {
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/", kTemp, 10 },
+ { "http://foo.com:8080/", kTemp, 20 },
+ { "http://bar.com/", kTemp, 13 },
{ "http://foo.com/", kPerm, 40 },
};
RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData)));
@@ -1259,10 +1259,10 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) {
TEST_F(QuotaManagerTest, GetUsageAndQuotaForEviction) {
static const MockOriginData kData[] = {
- { "http://foo.com/", kTemp, 1 },
- { "http://foo.com:1/", kTemp, 20 },
+ { "http://foo.com/", kTemp, 1 },
+ { "http://foo.com:1/", kTemp, 20 },
{ "http://foo.com/", kPerm, 300 },
- { "http://unlimited/", kTemp, 4000 },
+ { "http://unlimited/", kTemp, 4000 },
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
@@ -1388,17 +1388,16 @@ TEST_F(QuotaManagerTest, GetCachedOrigins) {
GetCachedOrigins(kTemp, &origins);
EXPECT_TRUE(origins.empty());
- // No matter how we make queries the quota manager tries to cache all
- // the origins at startup.
+ // Make the cache hot.
GetHostUsage("a.com", kTemp);
MessageLoop::current()->RunAllPending();
GetCachedOrigins(kTemp, &origins);
- EXPECT_EQ(3U, origins.size());
+ EXPECT_EQ(2U, origins.size());
GetHostUsage("b.com", kTemp);
MessageLoop::current()->RunAllPending();
GetCachedOrigins(kTemp, &origins);
- EXPECT_EQ(3U, origins.size());
+ EXPECT_EQ(2U, origins.size());
GetCachedOrigins(kPerm, &origins);
EXPECT_TRUE(origins.empty());
diff --git a/webkit/quota/quota_temporary_storage_evictor.cc b/webkit/quota/quota_temporary_storage_evictor.cc
index 1ad329a..f4b6750 100644
--- a/webkit/quota/quota_temporary_storage_evictor.cc
+++ b/webkit/quota/quota_temporary_storage_evictor.cc
@@ -4,7 +4,6 @@
#include "webkit/quota/quota_temporary_storage_evictor.h"
-#include "base/bind.h"
#include "base/metrics/histogram.h"
#include "googleurl/src/gurl.h"
#include "webkit/quota/quota_manager.h"
@@ -22,16 +21,17 @@
namespace {
const int64 kMBytes = 1024 * 1024;
-const double kUsageRatioToStartEviction = 0.7;
-const int kThresholdOfErrorsToStopEviction = 5;
-const base::TimeDelta kHistogramReportInterval =
- base::TimeDelta::FromMilliseconds(60 * 60 * 1000); // 1 hour
}
namespace quota {
+const double QuotaTemporaryStorageEvictor::kUsageRatioToStartEviction = 0.7;
const int QuotaTemporaryStorageEvictor::
kMinAvailableDiskSpaceToStartEvictionNotSpecified = -1;
+const int QuotaTemporaryStorageEvictor::kThresholdOfErrorsToStopEviction = 5;
+
+const base::TimeDelta QuotaTemporaryStorageEvictor::kHistogramReportInterval =
+ base::TimeDelta::FromMilliseconds(60 * 60 * 1000); // 1 hour
QuotaTemporaryStorageEvictor::QuotaTemporaryStorageEvictor(
QuotaEvictionHandler* quota_eviction_handler,
@@ -41,8 +41,7 @@ QuotaTemporaryStorageEvictor::QuotaTemporaryStorageEvictor(
quota_eviction_handler_(quota_eviction_handler),
interval_ms_(interval_ms),
repeated_eviction_(true),
- callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
- weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
DCHECK(quota_eviction_handler);
}
@@ -144,33 +143,32 @@ void QuotaTemporaryStorageEvictor::ConsiderEviction() {
OnEvictionRoundStarted();
// Get usage and disk space, then continue.
- quota_eviction_handler_->GetUsageAndQuotaForEviction(
- base::Bind(&QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction,
- weak_factory_.GetWeakPtr()));
+ quota_eviction_handler_->GetUsageAndQuotaForEviction(callback_factory_.
+ NewCallback(
+ &QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction));
}
void QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction(
QuotaStatusCode status,
- const QuotaAndUsage& qau) {
+ int64 usage,
+ int64 unlimited_usage,
+ int64 quota,
+ int64 available_disk_space) {
DCHECK(CalledOnValidThread());
+ DCHECK_GE(usage, unlimited_usage); // unlimited_usage is a subset of usage
- // unlimited_usage is a subset of usage
- DCHECK_GE(qau.usage, qau.unlimited_usage);
-
- int64 usage = qau.usage - qau.unlimited_usage;
+ usage -= unlimited_usage;
if (status != kQuotaStatusOk)
++statistics_.num_errors_on_getting_usage_and_quota;
int64 usage_overage = std::max(
static_cast<int64>(0),
- usage - static_cast<int64>(qau.quota * kUsageRatioToStartEviction));
+ usage - static_cast<int64>(quota * kUsageRatioToStartEviction));
- // min_available_disk_space_to_start_eviction_ might be < 0 if no value
- // is explicitly configured yet.
int64 diskspace_shortage = std::max(
static_cast<int64>(0),
- min_available_disk_space_to_start_eviction_ - qau.available_disk_space);
+ min_available_disk_space_to_start_eviction_ - available_disk_space);
if (!round_statistics_.is_initialized) {
round_statistics_.usage_overage_at_round = usage_overage;
diff --git a/webkit/quota/quota_temporary_storage_evictor.h b/webkit/quota/quota_temporary_storage_evictor.h
index a537171..e65dd80 100644
--- a/webkit/quota/quota_temporary_storage_evictor.h
+++ b/webkit/quota/quota_temporary_storage_evictor.h
@@ -10,7 +10,6 @@
#include <string>
#include "base/memory/scoped_callback_factory.h"
-#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "base/timer.h"
#include "webkit/quota/quota_types.h"
@@ -24,7 +23,6 @@ class MessageLoopProxy;
namespace quota {
class QuotaEvictionHandler;
-struct QuotaAndUsage;
class QuotaTemporaryStorageEvictor : public base::NonThreadSafe {
public:
@@ -102,7 +100,10 @@ class QuotaTemporaryStorageEvictor : public base::NonThreadSafe {
void ConsiderEviction();
void OnGotUsageAndQuotaForEviction(
QuotaStatusCode status,
- const QuotaAndUsage& quota_and_usage);
+ int64 usage,
+ int64 unlimited_usage,
+ int64 quota,
+ int64 available_disk_space);
void OnGotLRUOrigin(const GURL& origin);
void OnEvictionComplete(QuotaStatusCode status);
@@ -114,7 +115,10 @@ class QuotaTemporaryStorageEvictor : public base::NonThreadSafe {
repeated_eviction_ = repeated_eviction;
}
+ static const double kUsageRatioToStartEviction;
static const int kMinAvailableDiskSpaceToStartEvictionNotSpecified;
+ static const int kThresholdOfErrorsToStopEviction;
+ static const base::TimeDelta kHistogramReportInterval;
int64 min_available_disk_space_to_start_eviction_;
@@ -134,7 +138,6 @@ class QuotaTemporaryStorageEvictor : public base::NonThreadSafe {
base::RepeatingTimer<QuotaTemporaryStorageEvictor> histogram_timer_;
base::ScopedCallbackFactory<QuotaTemporaryStorageEvictor> callback_factory_;
- base::WeakPtrFactory<QuotaTemporaryStorageEvictor> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(QuotaTemporaryStorageEvictor);
};
diff --git a/webkit/quota/quota_temporary_storage_evictor_unittest.cc b/webkit/quota/quota_temporary_storage_evictor_unittest.cc
index 398ba50..6e857c7 100644
--- a/webkit/quota/quota_temporary_storage_evictor_unittest.cc
+++ b/webkit/quota/quota_temporary_storage_evictor_unittest.cc
@@ -7,7 +7,6 @@
#include <list>
#include <map>
-#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
@@ -49,16 +48,17 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler {
}
virtual void GetUsageAndQuotaForEviction(
- const GetUsageAndQuotaForEvictionCallback& callback) OVERRIDE {
+ GetUsageAndQuotaForEvictionCallback* callback) OVERRIDE {
if (error_on_get_usage_and_quota_) {
- callback.Run(quota::kQuotaErrorInvalidAccess, QuotaAndUsage());
+ callback->Run(quota::kQuotaErrorInvalidAccess, 0, 0, 0, 0);
+ delete callback;
return;
}
if (task_for_get_usage_and_quota_.get())
task_for_get_usage_and_quota_->Run();
- QuotaAndUsage quota_and_usage = {
- GetUsage(), unlimited_usage_, quota_, available_space_ };
- callback.Run(quota::kQuotaStatusOk, quota_and_usage);
+ callback->Run(quota::kQuotaStatusOk, GetUsage(), unlimited_usage_,
+ quota_, available_space_);
+ delete callback;
}
virtual void GetLRUOrigin(
diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi
index ff8c757..886f7f6 100644
--- a/webkit/tools/test_shell/test_shell.gypi
+++ b/webkit/tools/test_shell/test_shell.gypi
@@ -448,13 +448,13 @@
'../../plugins/ppapi/resource_tracker_unittest.cc',
'../../plugins/ppapi/time_conversion_unittest.cc',
'../../plugins/ppapi/url_request_info_unittest.cc',
- '../../quota/mock_quota_manager.cc',
- '../../quota/mock_quota_manager.h',
- '../../quota/mock_quota_manager_unittest.cc',
'../../quota/mock_special_storage_policy.cc',
'../../quota/mock_special_storage_policy.h',
'../../quota/mock_storage_client.cc',
'../../quota/mock_storage_client.h',
+ '../../quota/mock_quota_manager.cc',
+ '../../quota/mock_quota_manager.h',
+ '../../quota/mock_quota_manager_unittest.cc',
'../../quota/quota_database_unittest.cc',
'../../quota/quota_manager_unittest.cc',
'../../quota/quota_temporary_storage_evictor_unittest.cc',