summaryrefslogtreecommitdiffstats
path: root/webkit/quota
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/quota')
-rw-r--r--webkit/quota/mock_special_storage_policy.h4
-rw-r--r--webkit/quota/quota_manager_unittest.cc32
-rw-r--r--webkit/quota/special_storage_policy.cc15
-rw-r--r--webkit/quota/special_storage_policy.h19
-rw-r--r--webkit/quota/usage_tracker.cc37
-rw-r--r--webkit/quota/usage_tracker.h13
6 files changed, 109 insertions, 11 deletions
diff --git a/webkit/quota/mock_special_storage_policy.h b/webkit/quota/mock_special_storage_policy.h
index ec65fe3..3f3a873 100644
--- a/webkit/quota/mock_special_storage_policy.h
+++ b/webkit/quota/mock_special_storage_policy.h
@@ -39,6 +39,10 @@ class MockSpecialStoragePolicy : public quota::SpecialStoragePolicy {
file_handlers_.clear();
}
+ void NotifyChanged() {
+ SpecialStoragePolicy::NotifyObservers();
+ }
+
private:
std::set<GURL> protected_;
std::set<GURL> unlimited_;
diff --git a/webkit/quota/quota_manager_unittest.cc b/webkit/quota/quota_manager_unittest.cc
index 3e6b32a..2c828b3 100644
--- a/webkit/quota/quota_manager_unittest.cc
+++ b/webkit/quota/quota_manager_unittest.cc
@@ -710,6 +710,11 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) {
SetTemporaryGlobalQuota(1000);
MessageLoop::current()->RunAllPending();
+ GetGlobalUsage(kTemp);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(10 + 50 + 4000, usage());
+ EXPECT_EQ(4000, unlimited_usage());
+
const int kPerHostQuotaFor1000 =
1000 / QuotaManager::kPerHostTemporaryPortion;
@@ -755,6 +760,33 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) {
EXPECT_EQ(kQuotaStatusOk, status());
EXPECT_EQ(4000, usage());
EXPECT_EQ(kint64max, quota());
+
+ // Revoke the unlimited rights and make sure the change is noticed.
+ mock_special_storage_policy()->Reset();
+ mock_special_storage_policy()->NotifyChanged();
+
+ GetGlobalUsage(kTemp);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(10 + 50 + 4000, usage());
+ EXPECT_EQ(0, unlimited_usage());
+
+ GetUsageAndQuota(GURL("http://usage10/"), kTemp);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kQuotaStatusOk, status());
+ EXPECT_EQ(10, usage());
+ EXPECT_EQ(10, quota()); // should be clamped to our current usage
+
+ GetUsageAndQuota(GURL("http://usage50/"), kTemp);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kQuotaStatusOk, status());
+ EXPECT_EQ(50, usage());
+ EXPECT_EQ(kPerHostQuotaFor100, quota());
+
+ GetUsageAndQuota(GURL("http://unlimited/"), kTemp);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kQuotaStatusOk, status());
+ EXPECT_EQ(4000, usage());
+ EXPECT_EQ(kPerHostQuotaFor100, quota());
}
TEST_F(QuotaManagerTest, OriginInUse) {
diff --git a/webkit/quota/special_storage_policy.cc b/webkit/quota/special_storage_policy.cc
index c428346..8481239 100644
--- a/webkit/quota/special_storage_policy.cc
+++ b/webkit/quota/special_storage_policy.cc
@@ -6,8 +6,23 @@
namespace quota {
+SpecialStoragePolicy::Observer::~Observer() {}
+
SpecialStoragePolicy::SpecialStoragePolicy() {}
SpecialStoragePolicy::~SpecialStoragePolicy() {}
+void SpecialStoragePolicy::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void SpecialStoragePolicy::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void SpecialStoragePolicy::NotifyObservers() {
+ scoped_refptr<SpecialStoragePolicy> protect(this);
+ FOR_EACH_OBSERVER(Observer, observers_, OnSpecialStoragePolicyChanged());
+}
+
} // namespace quota
diff --git a/webkit/quota/special_storage_policy.h b/webkit/quota/special_storage_policy.h
index d9f1728..cc1af6b 100644
--- a/webkit/quota/special_storage_policy.h
+++ b/webkit/quota/special_storage_policy.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
class GURL;
@@ -17,10 +18,18 @@ namespace quota {
// storage subsystems query this interface to determine which origins
// have these rights. Chrome provides an impl that is cognizant of what
// is currently installed in the extensions system.
-// An implementation must be thread-safe.
+// The IsSomething() methods must be thread-safe, however Observers should
+// only be notified, added, and removed on the IO thead.
class SpecialStoragePolicy
: public base::RefCountedThreadSafe<SpecialStoragePolicy> {
public:
+ class Observer {
+ public:
+ virtual void OnSpecialStoragePolicyChanged() = 0;
+ protected:
+ virtual ~Observer();
+ };
+
SpecialStoragePolicy();
// Protected storage is not subject to removal by the browsing data remover.
@@ -33,9 +42,17 @@ class SpecialStoragePolicy
// file handler.
virtual bool IsFileHandler(const std::string& extension_id) = 0;
+ // Adds/removes an observer, the policy does not take
+ // ownership of the observer. Should only be called on the IO thread.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
protected:
friend class base::RefCountedThreadSafe<SpecialStoragePolicy>;
virtual ~SpecialStoragePolicy();
+ void NotifyObservers();
+
+ ObserverList<Observer> observers_;
};
} // namespace quota
diff --git a/webkit/quota/usage_tracker.cc b/webkit/quota/usage_tracker.cc
index 9a98bb1..60abf85 100644
--- a/webkit/quota/usage_tracker.cc
+++ b/webkit/quota/usage_tracker.cc
@@ -12,7 +12,6 @@
#include "base/message_loop_proxy.h"
#include "base/stl_util.h"
#include "net/base/net_util.h"
-#include "webkit/quota/special_storage_policy.h"
namespace quota {
@@ -334,18 +333,23 @@ ClientUsageTracker::ClientUsageTracker(
global_usage_(0),
global_unlimited_usage_(0),
global_usage_retrieved_(false),
+ global_unlimited_usage_is_valid_(true),
global_usage_task_(NULL),
special_storage_policy_(special_storage_policy) {
DCHECK(tracker_);
DCHECK(client_);
+ if (special_storage_policy_)
+ special_storage_policy_->AddObserver(this);
}
ClientUsageTracker::~ClientUsageTracker() {
+ if (special_storage_policy_)
+ special_storage_policy_->RemoveObserver(this);
}
void ClientUsageTracker::GetGlobalUsage(GlobalUsageCallback* callback) {
if (global_usage_retrieved_) {
- callback->Run(type_, global_usage_, global_unlimited_usage_);
+ callback->Run(type_, global_usage_, GetCachedGlobalUnlimitedUsage());
delete callback;
return;
}
@@ -377,7 +381,7 @@ void ClientUsageTracker::UpdateUsageCache(
if (cached_hosts_.find(host) != cached_hosts_.end()) {
cached_usage_[host][origin] += delta;
global_usage_ += delta;
- if (IsStorageUnlimited(origin))
+ if (global_unlimited_usage_is_valid_ && IsStorageUnlimited(origin))
global_unlimited_usage_ += delta;
DCHECK_GE(cached_usage_[host][origin], 0);
DCHECK_GE(global_usage_, 0);
@@ -411,7 +415,7 @@ void ClientUsageTracker::AddCachedOrigin(
int64 delta = usage - old_usage;
if (delta) {
global_usage_ += delta;
- if (IsStorageUnlimited(origin))
+ if (global_unlimited_usage_is_valid_ && IsStorageUnlimited(origin))
global_unlimited_usage_ += delta;
}
DCHECK_GE(iter->second, 0);
@@ -429,7 +433,8 @@ void ClientUsageTracker::GatherGlobalUsageComplete() {
global_usage_retrieved_ = true;
DCHECK(global_usage_callback_.HasCallbacks());
- global_usage_callback_.Run(type_, global_usage_, global_unlimited_usage_);
+ global_usage_callback_.Run(type_, global_usage_,
+ GetCachedGlobalUnlimitedUsage());
for (HostUsageCallbackMap::iterator iter = host_usage_callbacks_.Begin();
iter != host_usage_callbacks_.End(); ++iter) {
@@ -458,6 +463,28 @@ int64 ClientUsageTracker::GetCachedHostUsage(const std::string& host) {
return usage;
}
+int64 ClientUsageTracker::GetCachedGlobalUnlimitedUsage() {
+ if (!global_unlimited_usage_is_valid_) {
+ global_unlimited_usage_ = 0;
+ for (HostUsageMap::const_iterator host_iter = cached_usage_.begin();
+ host_iter != cached_usage_.end(); host_iter++) {
+ const UsageMap& origin_map = host_iter->second;
+ for (UsageMap::const_iterator origin_iter = origin_map.begin();
+ origin_iter != origin_map.end(); origin_iter++) {
+ if (IsStorageUnlimited(origin_iter->first))
+ global_unlimited_usage_ += origin_iter->second;
+ }
+ }
+ global_unlimited_usage_is_valid_ = true;
+ }
+ return global_unlimited_usage_;
+}
+
+void ClientUsageTracker::OnSpecialStoragePolicyChanged() {
+ DCHECK(CalledOnValidThread());
+ global_unlimited_usage_is_valid_ = false;
+}
+
void ClientUsageTracker::NoopHostUsageCallback(
const std::string& host, StorageType type, int64 usage) {
}
diff --git a/webkit/quota/usage_tracker.h b/webkit/quota/usage_tracker.h
index b4fc51b..258ef16 100644
--- a/webkit/quota/usage_tracker.h
+++ b/webkit/quota/usage_tracker.h
@@ -15,15 +15,16 @@
#include "base/callback.h"
#include "base/memory/scoped_callback_factory.h"
#include "base/memory/scoped_ptr.h"
+#include "base/threading/non_thread_safe.h"
#include "googleurl/src/gurl.h"
#include "webkit/quota/quota_client.h"
#include "webkit/quota/quota_task.h"
#include "webkit/quota/quota_types.h"
+#include "webkit/quota/special_storage_policy.h"
namespace quota {
class ClientUsageTracker;
-class SpecialStoragePolicy;
// A helper class that gathers and tracks the amount of data stored in
// all quota clients.
@@ -79,13 +80,14 @@ class UsageTracker : public QuotaTaskObserver {
// This class holds per-client usage tracking information and caches per-host
// usage data. An instance of this class is created per client.
-class ClientUsageTracker {
+class ClientUsageTracker : public SpecialStoragePolicy::Observer,
+ public base::NonThreadSafe {
public:
ClientUsageTracker(UsageTracker* tracker,
QuotaClient* client,
StorageType type,
SpecialStoragePolicy* special_storage_policy);
- ~ClientUsageTracker();
+ virtual ~ClientUsageTracker();
void GetGlobalUsage(GlobalUsageCallback* callback);
void GetHostUsage(const std::string& host, HostUsageCallback* callback);
@@ -109,10 +111,10 @@ class ClientUsageTracker {
void GatherHostUsageComplete(const std::string& host);
int64 GetCachedHostUsage(const std::string& host);
-
+ int64 GetCachedGlobalUnlimitedUsage();
+ virtual void OnSpecialStoragePolicyChanged() OVERRIDE;
void NoopHostUsageCallback(
const std::string& host, StorageType type, int64 usage);
-
bool IsStorageUnlimited(const GURL& origin) const;
UsageTracker* tracker_;
@@ -122,6 +124,7 @@ class ClientUsageTracker {
int64 global_usage_;
int64 global_unlimited_usage_;
bool global_usage_retrieved_;
+ bool global_unlimited_usage_is_valid_;
HostSet cached_hosts_;
HostUsageMap cached_usage_;