Home | History | Annotate | Download | only in quota
      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(&quota_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