diff options
author | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-15 23:34:09 +0000 |
---|---|---|
committer | michaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-15 23:34:09 +0000 |
commit | 608ba33299c6e11d9d21f561372237a3fbe23ce8 (patch) | |
tree | 3664e7eba4abe920a06a54e7004c82b014678b7a /webkit/quota | |
parent | 008521ab715815c43e6f9a1822fdf1ff8de37d25 (diff) | |
download | chromium_src-608ba33299c6e11d9d21f561372237a3fbe23ce8.zip chromium_src-608ba33299c6e11d9d21f561372237a3fbe23ce8.tar.gz chromium_src-608ba33299c6e11d9d21f561372237a3fbe23ce8.tar.bz2 |
Send notifications on the IO thread when changes are made to the special storage policy. Listen for those changes in the usage tracking system and fixup the cache to accurately reflect how much usage should be characterised as "unlimited" usage.
TEST=modified quota_manager_unittest.cc
Review URL: http://codereview.chromium.org/7618025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96858 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/quota')
-rw-r--r-- | webkit/quota/mock_special_storage_policy.h | 4 | ||||
-rw-r--r-- | webkit/quota/quota_manager_unittest.cc | 32 | ||||
-rw-r--r-- | webkit/quota/special_storage_policy.cc | 15 | ||||
-rw-r--r-- | webkit/quota/special_storage_policy.h | 19 | ||||
-rw-r--r-- | webkit/quota/usage_tracker.cc | 37 | ||||
-rw-r--r-- | webkit/quota/usage_tracker.h | 13 |
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_; |