Home | History | Annotate | Download | only in browser
      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 <map>
      6 
      7 #include "base/bind.h"
      8 #include "base/files/file_path.h"
      9 #include "base/message_loop/message_loop_proxy.h"
     10 #include "base/run_loop.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "net/base/completion_callback.h"
     13 #include "net/base/net_errors.h"
     14 #include "storage/browser/database/database_quota_client.h"
     15 #include "storage/browser/database/database_tracker.h"
     16 #include "storage/browser/database/database_util.h"
     17 #include "storage/common/database/database_identifier.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 using storage::DatabaseQuotaClient;
     21 using storage::DatabaseTracker;
     22 using storage::OriginInfo;
     23 
     24 namespace content {
     25 
     26 // Declared to shorten the line lengths.
     27 static const storage::StorageType kTemp = storage::kStorageTypeTemporary;
     28 static const storage::StorageType kPerm = storage::kStorageTypePersistent;
     29 
     30 // Mock tracker class the mocks up those methods of the tracker
     31 // that are used by the QuotaClient.
     32 class MockDatabaseTracker : public DatabaseTracker {
     33  public:
     34   MockDatabaseTracker()
     35       : DatabaseTracker(base::FilePath(), false, NULL, NULL, NULL),
     36         delete_called_count_(0),
     37         async_delete_(false) {}
     38 
     39   virtual bool GetOriginInfo(
     40       const std::string& origin_identifier,
     41       OriginInfo* info) OVERRIDE {
     42     std::map<GURL, MockOriginInfo>::const_iterator found =
     43         mock_origin_infos_.find(
     44             storage::GetOriginFromIdentifier(origin_identifier));
     45     if (found == mock_origin_infos_.end())
     46       return false;
     47     *info = OriginInfo(found->second);
     48     return true;
     49   }
     50 
     51   virtual bool GetAllOriginIdentifiers(
     52       std::vector<std::string>* origins_identifiers) OVERRIDE {
     53     std::map<GURL, MockOriginInfo>::const_iterator iter;
     54     for (iter = mock_origin_infos_.begin();
     55          iter != mock_origin_infos_.end();
     56          ++iter) {
     57       origins_identifiers->push_back(iter->second.GetOriginIdentifier());
     58     }
     59     return true;
     60   }
     61 
     62   virtual bool GetAllOriginsInfo(
     63       std::vector<OriginInfo>* origins_info) OVERRIDE {
     64     std::map<GURL, MockOriginInfo>::const_iterator iter;
     65     for (iter = mock_origin_infos_.begin();
     66          iter != mock_origin_infos_.end();
     67          ++iter) {
     68       origins_info->push_back(OriginInfo(iter->second));
     69     }
     70     return true;
     71   }
     72 
     73   virtual int DeleteDataForOrigin(
     74       const std::string& origin_identifier,
     75       const net::CompletionCallback& callback) OVERRIDE {
     76     ++delete_called_count_;
     77     if (async_delete()) {
     78       base::MessageLoopProxy::current()->PostTask(
     79           FROM_HERE,
     80           base::Bind(&MockDatabaseTracker::AsyncDeleteDataForOrigin, this,
     81                      callback));
     82       return net::ERR_IO_PENDING;
     83     }
     84     return net::OK;
     85   }
     86 
     87   void AsyncDeleteDataForOrigin(const net::CompletionCallback& callback) {
     88     callback.Run(net::OK);
     89   }
     90 
     91   void AddMockDatabase(const GURL& origin,  const char* name, int size) {
     92     MockOriginInfo& info = mock_origin_infos_[origin];
     93     info.set_origin(storage::GetIdentifierFromOrigin(origin));
     94     info.AddMockDatabase(base::ASCIIToUTF16(name), size);
     95   }
     96 
     97   int delete_called_count() { return delete_called_count_; }
     98   bool async_delete() { return async_delete_; }
     99   void set_async_delete(bool async) { async_delete_ = async; }
    100 
    101  protected:
    102   virtual ~MockDatabaseTracker() {}
    103 
    104  private:
    105   class MockOriginInfo : public OriginInfo {
    106    public:
    107     void set_origin(const std::string& origin_identifier) {
    108       origin_identifier_ = origin_identifier;
    109     }
    110 
    111     void AddMockDatabase(const base::string16& name, int size) {
    112       EXPECT_TRUE(database_info_.find(name) == database_info_.end());
    113       database_info_[name].first = size;
    114       total_size_ += size;
    115     }
    116   };
    117 
    118   int delete_called_count_;
    119   bool async_delete_;
    120   std::map<GURL, MockOriginInfo> mock_origin_infos_;
    121 };
    122 
    123 
    124 // Base class for our test fixtures.
    125 class DatabaseQuotaClientTest : public testing::Test {
    126  public:
    127   const GURL kOriginA;
    128   const GURL kOriginB;
    129   const GURL kOriginOther;
    130 
    131   DatabaseQuotaClientTest()
    132       : kOriginA("http://host"),
    133         kOriginB("http://host:8000"),
    134         kOriginOther("http://other"),
    135         usage_(0),
    136         mock_tracker_(new MockDatabaseTracker),
    137         weak_factory_(this) {
    138   }
    139 
    140   int64 GetOriginUsage(storage::QuotaClient* client,
    141                        const GURL& origin,
    142                        storage::StorageType type) {
    143     usage_ = 0;
    144     client->GetOriginUsage(
    145         origin, type,
    146         base::Bind(&DatabaseQuotaClientTest::OnGetOriginUsageComplete,
    147                    weak_factory_.GetWeakPtr()));
    148     base::RunLoop().RunUntilIdle();
    149     return usage_;
    150   }
    151 
    152   const std::set<GURL>& GetOriginsForType(storage::QuotaClient* client,
    153                                           storage::StorageType type) {
    154     origins_.clear();
    155     client->GetOriginsForType(
    156         type,
    157         base::Bind(&DatabaseQuotaClientTest::OnGetOriginsComplete,
    158                    weak_factory_.GetWeakPtr()));
    159     base::RunLoop().RunUntilIdle();
    160     return origins_;
    161   }
    162 
    163   const std::set<GURL>& GetOriginsForHost(storage::QuotaClient* client,
    164                                           storage::StorageType type,
    165                                           const std::string& host) {
    166     origins_.clear();
    167     client->GetOriginsForHost(
    168         type, host,
    169         base::Bind(&DatabaseQuotaClientTest::OnGetOriginsComplete,
    170                    weak_factory_.GetWeakPtr()));
    171     base::RunLoop().RunUntilIdle();
    172     return origins_;
    173   }
    174 
    175   bool DeleteOriginData(storage::QuotaClient* client,
    176                         storage::StorageType type,
    177                         const GURL& origin) {
    178     delete_status_ = storage::kQuotaStatusUnknown;
    179     client->DeleteOriginData(
    180         origin, type,
    181         base::Bind(&DatabaseQuotaClientTest::OnDeleteOriginDataComplete,
    182                    weak_factory_.GetWeakPtr()));
    183     base::RunLoop().RunUntilIdle();
    184     return delete_status_ == storage::kQuotaStatusOk;
    185   }
    186 
    187   MockDatabaseTracker* mock_tracker() { return mock_tracker_.get(); }
    188 
    189 
    190  private:
    191   void OnGetOriginUsageComplete(int64 usage) {
    192     usage_ = usage;
    193   }
    194 
    195   void OnGetOriginsComplete(const std::set<GURL>& origins) {
    196     origins_ = origins;
    197   }
    198 
    199   void OnDeleteOriginDataComplete(storage::QuotaStatusCode status) {
    200     delete_status_ = status;
    201   }
    202 
    203   base::MessageLoop message_loop_;
    204   int64 usage_;
    205   std::set<GURL> origins_;
    206   storage::QuotaStatusCode delete_status_;
    207   scoped_refptr<MockDatabaseTracker> mock_tracker_;
    208   base::WeakPtrFactory<DatabaseQuotaClientTest> weak_factory_;
    209 };
    210 
    211 
    212 TEST_F(DatabaseQuotaClientTest, GetOriginUsage) {
    213   DatabaseQuotaClient client(base::MessageLoopProxy::current().get(),
    214                              mock_tracker());
    215 
    216   EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kTemp));
    217   EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kPerm));
    218 
    219   mock_tracker()->AddMockDatabase(kOriginA, "fooDB", 1000);
    220   EXPECT_EQ(1000, GetOriginUsage(&client, kOriginA, kTemp));
    221   EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kPerm));
    222 
    223   EXPECT_EQ(0, GetOriginUsage(&client, kOriginB, kPerm));
    224   EXPECT_EQ(0, GetOriginUsage(&client, kOriginB, kTemp));
    225 }
    226 
    227 TEST_F(DatabaseQuotaClientTest, GetOriginsForHost) {
    228   DatabaseQuotaClient client(base::MessageLoopProxy::current().get(),
    229                              mock_tracker());
    230 
    231   EXPECT_EQ(kOriginA.host(), kOriginB.host());
    232   EXPECT_NE(kOriginA.host(), kOriginOther.host());
    233 
    234   std::set<GURL> origins = GetOriginsForHost(&client, kTemp, kOriginA.host());
    235   EXPECT_TRUE(origins.empty());
    236 
    237   mock_tracker()->AddMockDatabase(kOriginA, "fooDB", 1000);
    238   origins = GetOriginsForHost(&client, kTemp, kOriginA.host());
    239   EXPECT_EQ(origins.size(), 1ul);
    240   EXPECT_TRUE(origins.find(kOriginA) != origins.end());
    241 
    242   mock_tracker()->AddMockDatabase(kOriginB, "barDB", 1000);
    243   origins = GetOriginsForHost(&client, kTemp, kOriginA.host());
    244   EXPECT_EQ(origins.size(), 2ul);
    245   EXPECT_TRUE(origins.find(kOriginA) != origins.end());
    246   EXPECT_TRUE(origins.find(kOriginB) != origins.end());
    247 
    248   EXPECT_TRUE(GetOriginsForHost(&client, kPerm, kOriginA.host()).empty());
    249   EXPECT_TRUE(GetOriginsForHost(&client, kTemp, kOriginOther.host()).empty());
    250 }
    251 
    252 TEST_F(DatabaseQuotaClientTest, GetOriginsForType) {
    253   DatabaseQuotaClient client(base::MessageLoopProxy::current().get(),
    254                              mock_tracker());
    255 
    256   EXPECT_TRUE(GetOriginsForType(&client, kTemp).empty());
    257   EXPECT_TRUE(GetOriginsForType(&client, kPerm).empty());
    258 
    259   mock_tracker()->AddMockDatabase(kOriginA, "fooDB", 1000);
    260   std::set<GURL> origins = GetOriginsForType(&client, kTemp);
    261   EXPECT_EQ(origins.size(), 1ul);
    262   EXPECT_TRUE(origins.find(kOriginA) != origins.end());
    263 
    264   EXPECT_TRUE(GetOriginsForType(&client, kPerm).empty());
    265 }
    266 
    267 TEST_F(DatabaseQuotaClientTest, DeleteOriginData) {
    268   DatabaseQuotaClient client(base::MessageLoopProxy::current().get(),
    269                              mock_tracker());
    270 
    271   // Perm deletions are short circuited in the Client and
    272   // should not reach the DatabaseTracker.
    273   EXPECT_TRUE(DeleteOriginData(&client, kPerm, kOriginA));
    274   EXPECT_EQ(0, mock_tracker()->delete_called_count());
    275 
    276   mock_tracker()->set_async_delete(false);
    277   EXPECT_TRUE(DeleteOriginData(&client, kTemp, kOriginA));
    278   EXPECT_EQ(1, mock_tracker()->delete_called_count());
    279 
    280   mock_tracker()->set_async_delete(true);
    281   EXPECT_TRUE(DeleteOriginData(&client, kTemp, kOriginA));
    282   EXPECT_EQ(2, mock_tracker()->delete_called_count());
    283 }
    284 
    285 }  // namespace content
    286