1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/bind.h" 6 #include "base/run_loop.h" 7 #include "content/public/test/mock_special_storage_policy.h" 8 #include "net/base/net_util.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 #include "webkit/browser/quota/usage_tracker.h" 11 12 using quota::kQuotaStatusOk; 13 using quota::kStorageTypeTemporary; 14 using quota::QuotaClient; 15 using quota::QuotaClientList; 16 using quota::SpecialStoragePolicy; 17 using quota::StorageType; 18 using quota::UsageTracker; 19 20 namespace content { 21 22 namespace { 23 24 void DidGetGlobalUsage(bool* done, 25 int64* usage_out, 26 int64* unlimited_usage_out, 27 int64 usage, 28 int64 unlimited_usage) { 29 EXPECT_FALSE(*done); 30 *done = true; 31 *usage_out = usage; 32 *unlimited_usage_out = unlimited_usage; 33 } 34 35 void DidGetUsage(bool* done, 36 int64* usage_out, 37 int64 usage) { 38 EXPECT_FALSE(*done); 39 *done = true; 40 *usage_out = usage; 41 } 42 43 } // namespace 44 45 class MockQuotaClient : public QuotaClient { 46 public: 47 MockQuotaClient() {} 48 virtual ~MockQuotaClient() {} 49 50 virtual ID id() const OVERRIDE { 51 return kFileSystem; 52 } 53 54 virtual void OnQuotaManagerDestroyed() OVERRIDE {} 55 56 virtual void GetOriginUsage(const GURL& origin, 57 StorageType type, 58 const GetUsageCallback& callback) OVERRIDE { 59 EXPECT_EQ(kStorageTypeTemporary, type); 60 int64 usage = GetUsage(origin); 61 base::MessageLoop::current()->PostTask(FROM_HERE, 62 base::Bind(callback, usage)); 63 } 64 65 virtual void GetOriginsForType(StorageType type, 66 const GetOriginsCallback& callback) OVERRIDE { 67 EXPECT_EQ(kStorageTypeTemporary, type); 68 std::set<GURL> origins; 69 for (UsageMap::const_iterator itr = usage_map_.begin(); 70 itr != usage_map_.end(); ++itr) { 71 origins.insert(itr->first); 72 } 73 base::MessageLoop::current()->PostTask(FROM_HERE, 74 base::Bind(callback, origins)); 75 } 76 77 virtual void GetOriginsForHost(StorageType type, 78 const std::string& host, 79 const GetOriginsCallback& callback) OVERRIDE { 80 EXPECT_EQ(kStorageTypeTemporary, type); 81 std::set<GURL> origins; 82 for (UsageMap::const_iterator itr = usage_map_.begin(); 83 itr != usage_map_.end(); ++itr) { 84 if (net::GetHostOrSpecFromURL(itr->first) == host) 85 origins.insert(itr->first); 86 } 87 base::MessageLoop::current()->PostTask(FROM_HERE, 88 base::Bind(callback, origins)); 89 } 90 91 virtual void DeleteOriginData(const GURL& origin, 92 StorageType type, 93 const DeletionCallback& callback) OVERRIDE { 94 EXPECT_EQ(kStorageTypeTemporary, type); 95 usage_map_.erase(origin); 96 base::MessageLoop::current()->PostTask( 97 FROM_HERE, base::Bind(callback, kQuotaStatusOk)); 98 } 99 100 virtual bool DoesSupport(quota::StorageType type) const OVERRIDE { 101 return type == quota::kStorageTypeTemporary; 102 } 103 104 int64 GetUsage(const GURL& origin) { 105 UsageMap::const_iterator found = usage_map_.find(origin); 106 if (found == usage_map_.end()) 107 return 0; 108 return found->second; 109 } 110 111 void SetUsage(const GURL& origin, int64 usage) { 112 usage_map_[origin] = usage; 113 } 114 115 int64 UpdateUsage(const GURL& origin, int64 delta) { 116 return usage_map_[origin] += delta; 117 } 118 119 private: 120 typedef std::map<GURL, int64> UsageMap; 121 122 UsageMap usage_map_; 123 124 DISALLOW_COPY_AND_ASSIGN(MockQuotaClient); 125 }; 126 127 class UsageTrackerTest : public testing::Test { 128 public: 129 UsageTrackerTest() 130 : storage_policy_(new MockSpecialStoragePolicy()), 131 usage_tracker_(GetUsageTrackerList(), kStorageTypeTemporary, 132 storage_policy_.get(), NULL) { 133 } 134 135 virtual ~UsageTrackerTest() {} 136 137 UsageTracker* usage_tracker() { 138 return &usage_tracker_; 139 } 140 141 void UpdateUsage(const GURL& origin, int64 delta) { 142 quota_client_.UpdateUsage(origin, delta); 143 usage_tracker_.UpdateUsageCache(quota_client_.id(), origin, delta); 144 base::RunLoop().RunUntilIdle(); 145 } 146 147 void UpdateUsageWithoutNotification(const GURL& origin, int64 delta) { 148 quota_client_.UpdateUsage(origin, delta); 149 } 150 151 void GetGlobalLimitedUsage(int64* limited_usage) { 152 bool done = false; 153 usage_tracker_.GetGlobalLimitedUsage(base::Bind( 154 &DidGetUsage, &done, limited_usage)); 155 base::RunLoop().RunUntilIdle(); 156 157 EXPECT_TRUE(done); 158 } 159 160 void GetGlobalUsage(int64* usage, int64* unlimited_usage) { 161 bool done = false; 162 usage_tracker_.GetGlobalUsage(base::Bind( 163 &DidGetGlobalUsage, 164 &done, usage, unlimited_usage)); 165 base::RunLoop().RunUntilIdle(); 166 167 EXPECT_TRUE(done); 168 } 169 170 void GetHostUsage(const std::string& host, int64* usage) { 171 bool done = false; 172 usage_tracker_.GetHostUsage(host, base::Bind(&DidGetUsage, &done, usage)); 173 base::RunLoop().RunUntilIdle(); 174 175 EXPECT_TRUE(done); 176 } 177 178 void GrantUnlimitedStoragePolicy(const GURL& origin) { 179 if (!storage_policy_->IsStorageUnlimited(origin)) { 180 storage_policy_->AddUnlimited(origin); 181 storage_policy_->NotifyGranted( 182 origin, SpecialStoragePolicy::STORAGE_UNLIMITED); 183 } 184 } 185 186 void RevokeUnlimitedStoragePolicy(const GURL& origin) { 187 if (storage_policy_->IsStorageUnlimited(origin)) { 188 storage_policy_->RemoveUnlimited(origin); 189 storage_policy_->NotifyRevoked( 190 origin, SpecialStoragePolicy::STORAGE_UNLIMITED); 191 } 192 } 193 194 void SetUsageCacheEnabled(const GURL& origin, bool enabled) { 195 usage_tracker_.SetUsageCacheEnabled( 196 quota_client_.id(), origin, enabled); 197 } 198 199 private: 200 QuotaClientList GetUsageTrackerList() { 201 QuotaClientList client_list; 202 client_list.push_back("a_client_); 203 return client_list; 204 } 205 206 base::MessageLoop message_loop_; 207 208 scoped_refptr<MockSpecialStoragePolicy> storage_policy_; 209 MockQuotaClient quota_client_; 210 UsageTracker usage_tracker_; 211 212 DISALLOW_COPY_AND_ASSIGN(UsageTrackerTest); 213 }; 214 215 TEST_F(UsageTrackerTest, GrantAndRevokeUnlimitedStorage) { 216 int64 usage = 0; 217 int64 unlimited_usage = 0; 218 int64 host_usage = 0; 219 GetGlobalUsage(&usage, &unlimited_usage); 220 EXPECT_EQ(0, usage); 221 EXPECT_EQ(0, unlimited_usage); 222 223 const GURL origin("http://example.com"); 224 const std::string host(net::GetHostOrSpecFromURL(origin)); 225 226 UpdateUsage(origin, 100); 227 GetGlobalUsage(&usage, &unlimited_usage); 228 GetHostUsage(host, &host_usage); 229 EXPECT_EQ(100, usage); 230 EXPECT_EQ(0, unlimited_usage); 231 EXPECT_EQ(100, host_usage); 232 233 GrantUnlimitedStoragePolicy(origin); 234 GetGlobalUsage(&usage, &unlimited_usage); 235 GetHostUsage(host, &host_usage); 236 EXPECT_EQ(100, usage); 237 EXPECT_EQ(100, unlimited_usage); 238 EXPECT_EQ(100, host_usage); 239 240 RevokeUnlimitedStoragePolicy(origin); 241 GetGlobalUsage(&usage, &unlimited_usage); 242 GetHostUsage(host, &host_usage); 243 EXPECT_EQ(100, usage); 244 EXPECT_EQ(0, unlimited_usage); 245 EXPECT_EQ(100, host_usage); 246 } 247 248 TEST_F(UsageTrackerTest, CacheDisabledClientTest) { 249 int64 usage = 0; 250 int64 unlimited_usage = 0; 251 int64 host_usage = 0; 252 253 const GURL origin("http://example.com"); 254 const std::string host(net::GetHostOrSpecFromURL(origin)); 255 256 UpdateUsage(origin, 100); 257 GetGlobalUsage(&usage, &unlimited_usage); 258 GetHostUsage(host, &host_usage); 259 EXPECT_EQ(100, usage); 260 EXPECT_EQ(0, unlimited_usage); 261 EXPECT_EQ(100, host_usage); 262 263 UpdateUsageWithoutNotification(origin, 100); 264 GetGlobalUsage(&usage, &unlimited_usage); 265 GetHostUsage(host, &host_usage); 266 EXPECT_EQ(100, usage); 267 EXPECT_EQ(0, unlimited_usage); 268 EXPECT_EQ(100, host_usage); 269 270 GrantUnlimitedStoragePolicy(origin); 271 UpdateUsageWithoutNotification(origin, 100); 272 SetUsageCacheEnabled(origin, false); 273 UpdateUsageWithoutNotification(origin, 100); 274 275 GetGlobalUsage(&usage, &unlimited_usage); 276 GetHostUsage(host, &host_usage); 277 EXPECT_EQ(400, usage); 278 EXPECT_EQ(400, unlimited_usage); 279 EXPECT_EQ(400, host_usage); 280 281 RevokeUnlimitedStoragePolicy(origin); 282 GetGlobalUsage(&usage, &unlimited_usage); 283 GetHostUsage(host, &host_usage); 284 EXPECT_EQ(400, usage); 285 EXPECT_EQ(0, unlimited_usage); 286 EXPECT_EQ(400, host_usage); 287 288 SetUsageCacheEnabled(origin, true); 289 UpdateUsage(origin, 100); 290 291 GetGlobalUsage(&usage, &unlimited_usage); 292 GetHostUsage(host, &host_usage); 293 EXPECT_EQ(500, usage); 294 EXPECT_EQ(0, unlimited_usage); 295 EXPECT_EQ(500, host_usage); 296 } 297 298 TEST_F(UsageTrackerTest, LimitedGlobalUsageTest) { 299 const GURL kNormal("http://normal"); 300 const GURL kUnlimited("http://unlimited"); 301 const GURL kNonCached("http://non_cached"); 302 const GURL kNonCachedUnlimited("http://non_cached-unlimited"); 303 304 GrantUnlimitedStoragePolicy(kUnlimited); 305 GrantUnlimitedStoragePolicy(kNonCachedUnlimited); 306 307 SetUsageCacheEnabled(kNonCached, false); 308 SetUsageCacheEnabled(kNonCachedUnlimited, false); 309 310 UpdateUsageWithoutNotification(kNormal, 1); 311 UpdateUsageWithoutNotification(kUnlimited, 2); 312 UpdateUsageWithoutNotification(kNonCached, 4); 313 UpdateUsageWithoutNotification(kNonCachedUnlimited, 8); 314 315 int64 limited_usage = 0; 316 int64 total_usage = 0; 317 int64 unlimited_usage = 0; 318 319 GetGlobalLimitedUsage(&limited_usage); 320 GetGlobalUsage(&total_usage, &unlimited_usage); 321 EXPECT_EQ(1 + 4, limited_usage); 322 EXPECT_EQ(1 + 2 + 4 + 8, total_usage); 323 EXPECT_EQ(2 + 8, unlimited_usage); 324 325 UpdateUsageWithoutNotification(kNonCached, 16 - 4); 326 UpdateUsageWithoutNotification(kNonCachedUnlimited, 32 - 8); 327 328 GetGlobalLimitedUsage(&limited_usage); 329 GetGlobalUsage(&total_usage, &unlimited_usage); 330 EXPECT_EQ(1 + 16, limited_usage); 331 EXPECT_EQ(1 + 2 + 16 + 32, total_usage); 332 EXPECT_EQ(2 + 32, unlimited_usage); 333 } 334 335 336 } // namespace content 337